可借鉴:https://www.cnblogs.com/xuyinhuan/p/5930287.html
public class MainActivity extends AppCompatActivity {
private TextView main_tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
main_tv = (TextView) findViewById(R.id.main_tv);
newThread(new Runnable() {
@Override
public void run() {
main_tv.setText("子线程中访问");
}
}).start();
}
}
也是很简单的几行,在onCreate方法中创建了一个子线程,并进行UI访问操作。
点击运行。你会发现即使在子线程中访问UI,程序一样能跑起来。结果如下所示:
咦,那为嘛以前在子线程中更新UI会报错呢?难道真的可以在子线程中访问UI?
先不急,这是一个极端的情况,修改MainActivity如下:
public class MainActivity extends AppCompatActivity {
private TextView main_tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
main_tv = (TextView) findViewById(R.id.main_tv);
newThread(new Runnable() {
@Override
publicvoid run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
main_tv.setText("子线程中访问");
}
}).start();
}
}
让子线程睡眠200毫秒,醒来后再进行UI访问。
结果你会发现,程序崩了。这才是正常的现象嘛。抛出了如下很熟悉的异常:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.Java:6581)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:924)
……
在onCreate()方法里面可以,在onCreate()新建一个子线程,我们发现程序并不会崩溃,正常运行,但是当我们让这个线程休眠2秒,或者更长时间。这时程序崩溃了。
这时我们是不是在想不是在子线程都不能更新UI的吗,怎么在onCreate()方法里面竟然可以正常运行?
答案:ViewRootImpl的创建在onResume方法回调之后,而我们一开篇是在onCreate方法中创建了子线程并访问UI,在那个时刻,ViewRootImpl是没有创建的,无法检测当前线程是否是UI线程,所以程序没有崩溃一样能跑起来,而之后修改了程序,让线程休眠了200毫秒后,程序就崩了。很明显200毫秒后ViewRootImpl已经创建了,可以执行checkThread方法检查当前线程。
这篇博客的分析如题目一样,Android中子线程真的不能更新UI吗?在onCreate方法中创建的子线程访问UI是一种极端的情况,这个不仔细分析源码是不知道的。
第二种说法:子线程检查方法checkThread()在ViewRootImpl中被调用,而ViewRootImpl在handleResumeActivity时被添加,也就是对应的是onResume()。所以也就是说在onCreate时根本不会执行checkThread()方法。
作者:MDove
链接:https://juejin.im/post/5b4563dee51d45190e34e531
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。