简体   繁体   English

计时器导致ViewRootImpl $ CalledFromWrongThreadException吗?

[英]Timer causing ViewRootImpl$CalledFromWrongThreadException?

I have a feeling my timer is causing this crash. 我感觉到我的计时器正在导致此崩溃。 Whats weird is I can't seem to reproduce it in my emulator, but my Play Console crash report is telling me users keep getting this crash: 奇怪的是我似乎无法在模拟器中重现它,但是我的Play控制台崩溃报告告诉我用户不断遇到此崩溃:

android.view.ViewRootImpl$CalledFromWrongThreadException: 
at android.view.ViewRootImpl.checkThread (ViewRootImpl.java:7988)
at android.view.ViewRootImpl.invalidateChildInParent (ViewRootImpl.java:1392)
at android.view.ViewGroup.invalidateChild (ViewGroup.java:5426)
at android.view.View.invalidateInternal (View.java:14959)
at android.view.View.invalidate (View.java:14923)
at android.view.View.invalidate (View.java:14907)
at android.widget.TextView.checkForRelayout (TextView.java:8624)
at android.widget.TextView.setText (TextView.java:5137)
at android.widget.TextView.setText (TextView.java:4962)
at android.widget.TextView.setText (TextView.java:4937)
at com.kjdion.smoketracker.MainActivity$1.run (MainActivity.java:97)
at java.util.TimerThread.mainLoop (Timer.java:555)
at java.util.TimerThread.run (Timer.java:505)

Here is my MainActivity code: 这是我的MainActivity代码:

package com.kjdion.smoketracker;

import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import com.facebook.stetho.Stetho;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    long longLast;
    boolean timerStarted = false;
    TextView sinceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MobileAds.initialize(this, "ca-app-pub-4097235499795154~8279081984");
        AdView mAdView = findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);

        //Stetho.initializeWithDefaults(this);
        setViews();
    }

    public void startLogActivity(View view) {
        Intent intent = new Intent(this, LogActivity.class);
        startActivity(intent);
    }

    public void startChartActivity(View view) {
        Intent intent = new Intent(this, ChartActivity.class);
        startActivity(intent);
    }

    public void startHealthActivity(View view) {
        Intent intent = new Intent(this, HealthActivity.class);
        startActivity(intent);
    }

    @Override
    public void onResume() {
        super.onResume();
        setViews();
    }

    public void setViews() {
        // init vars
        long date = Helpers.currentTime();
        String na = getResources().getString(R.string.text_na);
        String sinceLast = na;
        String longestGone = na;
        String smokedToday = na;
        String lowestDay = na;
        sinceView = findViewById(R.id.sinceLast);
        TextView longestView = findViewById(R.id.longestGone);
        TextView todayView = findViewById(R.id.smokedToday);
        TextView lowestView = findViewById(R.id.lowestDay);

        // grab db
        LogDatabaseHelper logDatabaseHelper = new LogDatabaseHelper(this);
        SQLiteDatabase database = logDatabaseHelper.getWritableDatabase();
        Cursor cursor;

        // since last
        cursor = database.rawQuery("" +
                "SELECT * " +
                "FROM " + LogDatabaseHelper.TABLE_NAME + " " +
                "ORDER BY id DESC " +
                "LIMIT 1", null);
        if (cursor.getCount() > 0) {
            cursor.moveToFirst();

            longLast = (date - cursor.getLong(cursor.getColumnIndex("date"))) * 1000;
            sinceLast = Helpers.toDuration(longLast);

            if (!timerStarted) {
                timerStarted = true;
                Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        // update since last text every second
                        sinceView.setText(Helpers.toDuration(longLast));
                        longLast = longLast + 1000;
                    }
                }, 0, 1000);
            }
        }
        cursor.close();

        // longest gone
        cursor = database.rawQuery("" +
                "SELECT * FROM " + LogDatabaseHelper.TABLE_NAME + " " +
                "ORDER BY length DESC " +
                "LIMIT 1" +
                "", null);
        if (cursor.getCount() > 0) {
            cursor.moveToFirst();

            long longGone = cursor.getLong(cursor.getColumnIndex("length")) * 1000;
            if (longGone > 0) {
                longestGone = Helpers.toDuration(longGone);
            }
        }
        cursor.close();

        // smoked today
        cursor = database.rawQuery("" +
                "SELECT sum(`amount`) as `sum` " +
                "FROM " + LogDatabaseHelper.TABLE_NAME + " " +
                "WHERE date(`date`, 'unixepoch') = date("+date+", 'unixepoch')" +
                "", null);
        if (cursor.getCount() > 0) {
            cursor.moveToFirst();

            if (!cursor.isNull(cursor.getColumnIndex("sum"))) {
                smokedToday = Helpers.toFraction(cursor.getDouble(cursor.getColumnIndex("sum")), 1000);
            }
        }
        cursor.close();

        // lowest day
        cursor = database.rawQuery("" +
                "SELECT sum(`amount`) as `sum` " +
                "FROM " + LogDatabaseHelper.TABLE_NAME + " " +
                "WHERE date(`date`, 'unixepoch') < date("+date+", 'unixepoch')" +
                "GROUP BY date(`date`, 'unixepoch') " +
                "ORDER BY `sum` ASC " +
                "LIMIT 1" +
                "", null);
        if (cursor.getCount() > 0) {
            cursor.moveToFirst();

            if (!cursor.isNull(cursor.getColumnIndex("sum"))) {
                lowestDay = Helpers.toFraction(cursor.getDouble(cursor.getColumnIndex("sum")), 1000);
            }
        }
        cursor.close();
        database.close();

        // set view text
        sinceView.setText(sinceLast);
        longestView.setText(longestGone);
        todayView.setText(smokedToday);
        lowestView.setText(lowestDay);
    }
}

Is the timer causing this? 是计时器造成的吗? Do I have to put the timer on the UI thread? 是否需要将计时器放在UI线程上?

The TimerTask is executed on a worker thread (non-UI thread). TimerTask在工作线程(非UI线程)上执行。 Your UI ( sinceView ) has to be accessed from the main (UI) thread. 您的UI( sinceView )必须从主(UI)线程访问。 There is a helper method in an Activity to do this: runOnUiThread . 目前处于一个辅助方法Activity要做到这一点: runOnUiThread

MainActivity.this.runOnUiThread(new Runnable() {
   sinceView.setText(Helpers.toDuration(longLast));
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android - ViewRootImpl$CalledFromWrongThreadException - Android - ViewRootImpl$CalledFromWrongThreadException android.view.viewrootimpl $ fromwrongthreadexception android java - android.view.viewrootimpl$calledfromwrongthreadexception android java Android编码:ViewRootImpl $ CalledFromWrongThreadException。 [菜鸟] - Android coding: ViewRootImpl$CalledFromWrongThreadException. [Noob] Android动态文本更新-ViewRootImpl $ CalledFromWrongThreadException - Dynamic Text Update for Android - ViewRootImpl$CalledFromWrongThreadException 为什么我收到异常ViewRootImpl $ CalledFromWrongThreadException? - Why i'm getting exception ViewRootImpl$CalledFromWrongThreadException? 当我按下按钮时,出现错误ViewRootImpl $ CalledFromWrongThreadException - When my button is pressed, I get the error ViewRootImpl$CalledFromWrongThreadException Flurry Agent在Android 2.3.4上导致CalledFromWrongThreadException异常 - Flurry Agent causing a CalledFromWrongThreadException exception on Android 2.3.4 android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图 - android.view.ViewRootImpl$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views 带有 scheduleAtFixedRate 的 Timer 和 TimerTask 导致更新 TextView 时 CalledFromWrongThreadException 崩溃 - Timer and TimerTask with scheduleAtFixedRate causes CalledFromWrongThreadException crash when updating TextView 使用计时器和paintComponent进行渲染不会导致渲染发生 - Rendering with a timer and paintComponent is causing no rendering to happen
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM