为什么ViewRootImpl $ CalledFromWrongThreadException不准确?

时间:2015-11-11 12:24:31

标签: android multithreading runtimeexception android-6.0-marshmallow android-handlerthread

更新TextView行到行(通过setText()旧行改为新行)的代码段来自非UI线程

TextView mLog;
final static String ONE_LINER;

// Condition 1: update from loopless thread
new Thread(new Runnable() {
    @Override
    public void run() {
        mLog.append(ONE_LINER);
    }
}).start();

// Condition 2: update from thread with Looper
HandlerThread handlerThread = new HandlerThread();
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        mLog.append(ONE_LINER);
    }
};
handler.sendEmptyMessage();

代码执行导致 CalledFromWrongThreadException 具有不同的堆栈跟踪(请检查下面的“Stacktrace#1”“Stacktrace#2”)。在两种变体下(从简单的无环线程更新View或从内部有Looper的 HandlerThread 更新)异常抛出不准确 - 每次UI更新后都不会发生事件通过工作线程。

是否有人想到为什么带有以下调用例程的系统行为(在相同的输入条件下)不持久?

Stacktrace#1 (频率:高;大部分时间)

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7900)
            at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1207)
            at android.view.ViewGroup.invalidateChild(ViewGroup.java:5424)
            at android.view.View.invalidateInternal(View.java:13884)
            at android.view.View.invalidate(View.java:13848)
            at android.view.View.invalidate(View.java:13832)
            at android.widget.TextView.updateAfterEdit(TextView.java:8918)
            at android.widget.TextView.handleTextChanged(TextView.java:8943)
            at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:11623)
            at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:1037)
            at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:563)
            at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:286)
            at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:34)
            at android.widget.TextView.append(TextView.java:4454)
            at android.widget.TextView.append(TextView.java:4441)

Stacktrace#2 (频率:罕见;捕获一次)

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7900)
            at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1170)
            at android.view.View.requestLayout(View.java:20043)
            at android.view.View.requestLayout(View.java:20043)
            at android.view.View.requestLayout(View.java:20043)
            at android.view.View.requestLayout(View.java:20043)
            at android.view.View.requestLayout(View.java:20043)
            at android.view.View.requestLayout(View.java:20043)
            at android.view.View.requestLayout(View.java:20043)
            at android.widget.TextView.checkForRelayout(TextView.java:8024)
            at android.widget.TextView.setText(TextView.java:4959)
            at android.widget.TextView.setText(TextView.java:4786)
            at android.widget.TextView.append(TextView.java:4451)
            at android.widget.TextView.append(TextView.java:4441)

注意

  1. No error “Only the original thread that created a view hierarchy can touch its views” when the view is updated without delay解释并未完全涵盖此问题(仅“Stacktrace#2”)。
  2. 操作系统:Android 6.0。

0 个答案:

没有答案