Android可不可以在子线程中更新UI?
我们首先来看一段代码:
在一个activity的xml文件中随便写一个TextView文本控件,然后在Activity的onCreate方法中开启一个子线程并在该子线程的run方法中更新TextView文本控件,你会发现根本没有任何问题。
但是如果你把Thread.sleep(2000)放开绘发现报错崩溃:
我们从这堆栈开始分析源码原因:
mButton.setText("woyaoniu");会调用android.widget.TextView#checkForRelayout方法中来,checkForRelayout继续调用android.view.View#requestLayout这里来:
我们来mParent是什么,首先它是一个ViewParent接口,requestLayout()是接口中定义的一个方法:
但是完整实现类却在View中,而不是ViewGroup中 虽然是ViewGroup实现了ViewParent接口
接着我们去看下View中mParent的来历:
View中的mParent成员变量通常来说指的就是当前View的父容器ViewGroup,但有一个特殊就是,对于顶层decorView来说它的mParent是ViewRootImpl。下面我们看源码来证实:
mParent通过方法assignParent(ViewParent parent)被赋值:
1 在ViewRootImpl中的setView方法中设置传递过来的DecorView,在该方法中会给DecorView中的mParent指定为当前ViewRootImpl,而且ViewRootImpl实现了ViewParent接口。
2 将View添加到ViewGroup中,通常使用addView(View child)等方法,最后会调用内部的addViewInner方法,将添加进来的子View的mParent设置为当前所在容器:
那么从调用android.view.View#requestLayout一直往上调用,最后会执行到ViewRootImpl#requestLayout方法
至此这个调用分析链报错就可以到这了。下面再看为啥注释掉Thread.sleep(2000)就没有报错呢:
根本原因就是ViewRootImpl到底是在哪初始化的呢!ViewRootImpl是在onResume中初始化的,而我们开启的子线程是在onCreate中,这个时候程序还没有去检测当前线程是不是主线程,所以就没有抛异常,下面我们去看ActivityThread源码,找出原因:
共有 0 条评论