初一看,这两个问题好像是矛盾的,其实不然:
首先,为什么子线程中更新UI不报错?
public class MainActivity extends Activity {
private TextView textview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
textview= (TextView) findViewById(R.id.textview);
new MyThread().start();
}
public class MyThread extends Thread{
@Override
public void run() {
textview.setText("子线程修改的");
}
}
}
程序正常运行。
为什么在onCreate里面能够启动非线程更新UI呢,那是因为onCreate时候,viewRoot还没有被创建,
if(mParent != null){
if (!mParent.isLayoutRequested()) {
mParent.requestLayout();
}
}
requestLayout()就不会被调用,所以没法执行检查
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
因为这个检查方法在view的requestLayout()里面被调用
那么在什么时候viewRoot会被创建呢,答案是执行onResume后,viewRoot就能创建好,这个时候就会执行UI线程检查了,所以在onCreate-
>onStart->onResume中都可以在子线程中更新UI。
第二个,为什么必须在主线程中操作UI?
如果不在主线程中操作UI,可能会造成如下的情况:
(1)两个线程同时设置同一个背景图片,那么很有可能因为当前图片被释放了两次而导致应用崩溃。
(2)两个线程同时设置同一个UIView的背景颜色,那么很有可能渲染显示的是颜色A,而此时在UIView逻辑树上的背景颜色属性为B。
(3)两个线程同时操作view的树形结构:在线程A中for循环遍历并操作当前View的所有subView,然后此时线程B中将某个subView直接删除,这就导致了错乱还可能导致应用崩溃。
参考:
https://bbs.csdn.net/topics/390600129?page=1
https://blog.csdn.net/wb1211/article/details/52092860
https://blog.csdn.net/potato512/article/details/55505666
http://www.cnblogs.com/yydcdut/p/3864072.html
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://mp.csdn.net/postedit/79908139