zoukankan      html  css  js  c++  java
  • Android 在非主线程无法操作UI意识

    Android在应用显示Dialog是一个非常easy事儿,但我从来没有尝试过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的认识,不知道是不是正确。









    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    在放置不同图片尺寸时,应该选择合适的放置
    在腾讯开发应用中心上架apk所遇到的问题
    仿慕课网下拉加载动画
    android 视频的缩略图 缓存机制和 异步加载缩略图
    在做Android开发的,如何去掉滚动view在尽头时的阴影效果
    java中常见的模式之自定义观察者和java库中观察者
    在JAVA和android中常用的单列模式
    android 代码控制控件的长宽,小技巧
    IFrame 框架的用法简介
    PHP中RabbitMQ之amqp扩展实现(四)
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4883203.html
Copyright © 2011-2022 走看看