0

非 UI スレッドから(古い行から新しい行へ) TextView を行ごとに更新するスニペット:setText()

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が発生します (以下の「スタック トレース#1」「スタック トレース #2」を確認してください)。両方のバリアント (単純なループレスThreadから、または内部に Looper を持つHandlerThreadから View を更新) では、例外のスローは正確ではありません。ワーカー スレッドを介した各 UI の更新後にイベントが正確に発生しません。

次の呼び出しルーチン (同じ入力条件) でのシステムの動作が持続しない理由を考えている人はいますか?

スタックトレース #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)

スタックトレース #2 (頻度: まれ; 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.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. ビューが遅滞なく更新されたときに、「ビュー階層を作成した元のスレッドのみがそのビューにアクセスできます」というエラーはありません。説明は問題を完全にはカバーしていません ( 「Stacktrace #2」のみ)。
  2. OS:アンドロイド6.0。
4

0 に答える 0