关于子线程操作view的一些实践分析

问题点:

最近在做与H5的交互中发现,通过@javascriptInterface提供的接口是运行在子线程中,但是在子线程中却能够操作View,这个有点颠覆了我学Android以来的认知,子线程不能更新view

于是写了demo做了几个实现,demo使用的sdk,目前测试过android-21,android-25和android-27

demo很简单,就是新建一个子线程,分别在里面作如下操作,来观察程序运行情况

一、API25和27的情况

view操作android-25,android-27上程序是否崩溃崩溃原因修复方法
TextView,Button:setText
Toast:show子线程未初始化loopershowToast前后增加Looper.prepare()和Looper.loop()
Dialog:show子线程未初始化looper(Can't create handler inside thread that has not called Looper.prepare())showDialog前后增加Looper.prepare()和Looper.loop()
Dialog:dismiss子线程不能操作view(Only the original thread that created a view hierarchy can touch its views)

 

一、API21的情况

view操作android-21是否会崩溃 崩溃原因修复方法
TextView,Button:setText子线程不能操作view(Only the original thread that created a view hierarchy can touch its views)

由表格可以发现:

1、API21上肯定会崩溃,这个符合我们对android子线程不能更新view的认知。

2、在API25和27上,我们常用的TextView或者是button是可以在子线程中更新view的但是dialog却不能dismiss,很奇怪,我仔细分析了一下Dialog.dimiss和TextView.setText的源码:

 

一、setText

setText的时候会调用View的invalidate()方法,跟进源码之后发现:最终会调用到ViewGroup中的这句话

该段代码就是表示在父view中更新子view,由于我demo的父view是RelativeLayout,RelativeLayout继承ViewGroup,所以走到了ViewGroup里面的更新view的方法,这里面一系列方法没有对线程的判断

二、Dialog.dismiss

Dialog dismiss时会调用windowManager的removeViewImmediate()方法

继续跟进windowManager的实现类windowManagerImpl,发现会走到ViewRootImpl类里面的这个方法,然后这里面有一个checkThread方法,这个就会导致抛出子线程不能更新view的错误。

继续研究源码,然后发现ViewRootImpl类里面也有一个ViewGroup类似的方法,viewGroup里面虽然有这个checkThread,但是更新view的时候没有调用到这个方法,所以ViewGroup里面更新view不会报错。

至此终于找到了罪魁祸首,综合以上,理论上来说,由于指观察了API21,25,27目前最起码25以上的API只要父view是继承ViewGroup就不会崩溃。

 

但是为什么dialog和toastshow的时候为什么只要初始化一下looper依然能在更新view呢?,下面对他们的show方法读了一下源码,

 

三、Dialog show和Toast show

这两个方法只要在子线程初始化一下Looper(Looper.prepare(),Looper.loop())就可以show出来。

这时候为什么可以在子线程更新View呢,还是分析源码,dialog和toast类似,会走到ViewrootImpl的checkThread方法,但是这时候确没有报异常,这时候观察源码

发现每次show的时候都会重新初始化这个ViewrootImpl,初始化的时候会给ViewrootImpl中的mThread赋值

就是当前线程,此时在子线程中,更新View的时候还是这个子线程,所有无论怎么判断,这两个线程都是同一个线程,所以不会报错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值