热点新闻
Android可不可以在子线程中更新UI?
2023-07-10 16:41  浏览:172  搜索引擎搜索“富博农业网”
温馨提示:信息一旦丢失不一定找得到,请务必收藏信息以备急用!本站所有信息均是注册会员发布如遇到侵权请联系文章中的联系方式或客服删除!
联系我时,请说明是在富博农业网看到的信息,谢谢。
展会发布 展会网站大全 报名观展合作 软文发布

我们首先来看一段代码:






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







发布人:88a6****    IP:223.213.65.***     举报/删稿
展会推荐
让朕来说2句
评论
收藏
点赞
转发