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源码,找出原因:

版权声明:
作者:admin
链接:https://www.techfm.club/p/48388.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>