【发布时间】:2015-12-07 11:44:34
【问题描述】:
我对 Android 系统的工作方式感到困惑,尤其是当它更新视图层次结构时。 我们都知道我们不应该从 UI(主)线程以外的任何线程更新任何视图。甚至当我们尝试这样做时,Android 系统也会抛出异常。 前几天我试图在我的应用程序中实现自定义进度显示视图。所以我开始使用标准的 Java 线程和处理程序组合。
我的发现让我感到惊讶,因为我能够从后台线程更新 TextView。
new Thread(new Runnable() {
@Override
public void run() {
mTextView.setText("I am " + Thread.currentThread().getName());
}
}).start();
之后我也尝试更新其他视图,效果很好。所以我尝试在后台线程中进行睡眠调用。
new Thread(new Runnable() {
@Override
public void run() {
mTextView.setText("Thread : before sleep");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mTextView.setText("Thread : after sleep");
}
}).start();
它按预期崩溃了
android.view.ViewRootImpl$CalledFromWrongThreadException: 只有 创建视图层次结构的原始线程可以触及其视图。
然后我尝试在 sleep() 调用之前和之后将 setText() 调用放入 循环 100、1000 次。当然,该应用程序每次都会崩溃,但我能够在我的文本视图上看到“睡前”文本。
所以我的问题是系统何时检测到某些非 UI 线程正在尝试更新视图。 为什么非 UI 线程中没有 sleep() 调用时它不起作用?
【问题讨论】:
-
只需使用 android.os.Handler - 它总是会在 UI 线程上运行它的可运行对象。
-
什么时候?见
android/view/ViewRootImpl.java方法名是checkThread -
@Dogcat :我知道 Handler。但我的问题是,为什么在第一种情况下系统不会崩溃?
-
我的问题是,为什么系统会这样,只是有时抛出异常,为什么不是每次。 Thread.sleep() 如何改变系统行为?
-
@pskink :实际上我从不接触非 UI 线程的 UI 元素,事实上我很少使用线程。我的一位同事(大学新生)做了这样的事情,所以我想到了这个疑问。顺便说一句,我的怀疑就在“你不能这样做”这一点上,因为我能够做到。系统行为不一致。
标签: android multithreading textview android-view background-thread