Android 关于非主线程不能操作UI的认识

Android在应用里显示Dialog是个很简单的事情,但是一直没试过在Service里面显示Dialog。根据之前的经验UI操作要在主线程,本地的服务Service是主线程里没错,但是远程service里面显示Dialog,听起来是不是就应该没有在主线程里面了呢?

        尝试一下就知道了,写了个AIDL的调用,client端去调用AIDL,在Service这边就是去显示一个Dialog。AIDL的部分就忽略了。Service这边的代码就和Activity上显示dialog一样。

AlertDialog.Builder builder = new AlertDialog.Builder(mContext);  
builder.setTitle("TEST");  
builder.setMessage("test");  
builder.show();

当然dialog要setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

结果呢,悲剧了。

Can't create handler inside thread that has not called Looper.prepare()
什么意思呢,主观理解,要显示个Dialog需要有消息循环的支持,给它一个消息循环就好了呗。但是,问题来了。。。 这个过程发生在哪个线程上呢,后来调试发现原来每次binder调用过来都会有一个线程出现,而且还是每次都是不一样的,估计是从一个线程池里面拿的。

那怎么给这个线程加上looper呢,没办法只能自己开一个线程了,果然在一个带looper的线程里去显示dailog貌似就没问题了。


那么问题又来了,为什么显示Dialog需要looper的支持呢?

看代码:

原来Dialog有一个

 private final Handler mHandler = new Handler();
还有一个

 mListenersHandler = new ListenersHandler(this);
看起来这两个Handler都是长在当前这个线程上的,那就明白了为什么show Dialog一定要looper了吧。


最后还有一个问题,一直说UI操作必须要在主线程,那上面说的这个情况就有点奇怪了,显现Service是远程的,显示dialog又是Service的一个子线程,跟主线程有半毛钱关系吗?费解了,以我个人理解,这个非主线程不操作UI看来并不是绝对的吧。

再仔细想想,之前有看到过,其实无论是Dialog还是Acitivty本质上都是通过WindowManager往window上加了一个view(ViewRoot),所有的view不可能是只属于一个client,各个client都在这个window上分了一杯羹,那么,有多个线程会去更新各自的view也就不奇怪了。只是每一个View本身只能有一个线程来操作罢了。这就是我对非主线程不能操作UI的认识,不知道是不是正确。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值