在android开发中经常会有更新UI的操作,有时候我们发现更新时会报出android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views的异常,这是怎么回事呢!原来是我们在子线程更新UI了,因为在Android中更新UI只能在主线程中执行。但是不是凡事都有例外呢?可以看下面的代码
public class MainActivity extends Activity {
private TextView tvText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvText = (TextView) findViewById(R.id.main_tv);
new Thread(new Runnable() {
@Override
public void run() {
tvText.setText("OtherThread");
}
}).start();
}
这段代码操作起来并没有问题,说明在子线程是可以更新的,那是不是说书上讲错了呢!其实不是
public class MainActivity extends Activity {
private TextView tvText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvText = (TextView) findViewById(R.id.main_tv);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
tvText.setText("OtherThread");
}
}).start();
}
}
像这样当我们在子线程了睡了200毫秒时我们发现,代码又不能用了,我们分析异常发现原因出在at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6581)
ViewRootImpl。checkThread是系统的方法
点进去看发现
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
在这里系统声明了只有主线程才可以更新UI,当每次UI更新时ViewRootImpl的checkThread()会检查当前线程是否为主线程,不是就会抛出异常,那为什么我们最上面的代码没问题呢?因为ViewRootImpl这个类是在onResume()方法里创建,在oncreate里是没有的,所以没报错。如果是耗时操作的话ViewRootImpl已创建一样会报错。