UUTON

悠悠途恩

Android handler要点分析


在handler的简单用法中,我们自己简单new出一个handler 然后调用它的sendMessage方法发出一条消息。然后在handler类重写了handler的handlerMessage方法来进行处理。看似就是这么简单的俩步,其实背后隐藏了很多我们不知道的流程。

   在介绍这个之前,我先介绍几个概念

1.Message

这个应该很清楚吧 就是我们发送的消息 介绍一个里面的一个方法Message.obtain函数。作用是从Message Pool中取出一个Message,如果Message Pool中已经没有Message可取则新建一个Message返回,同时用对应的参数给得到的Message对象赋值。 message Pool 我的理解就是一个缓存区。就是把用过的Message放进这里面为了以后用而已。要不每次都要new一个message起步麻烦。这个应该跟String pool的原理一样。姑且我们把它视为同一个作用的东西。

2.MessageQueue

顾名思义就是消息队列,干什么用的 当然是存放消息用的

3.Looper 

我暂且叫他循环体吧。 主要就是从MessageQueue中读取消息。

4.handler 

当然就是处理发来的消息了

下面我就把这个四个联系起来,看看他们在内部到底怎么执行。

首先通过handler发出一条消息,发送到MessageQueue消息队列里,

接着通过Loop从MessageQueue中从前往后取出Message,

然后通过Handler的dispatchMessage函数进行消息的处理(可见消息的处理是Handler负责的),

消息处理完了以后通过Message对象的recycle(回收利用)函数放到Message Pool中,以便下次使用,通过Pool的处理提供了一定的内存管理从而加速消息对象的获取。

 

  


那looper 和messagequeue什么时候生成呢。

其实messagequeue在Looper创建的时候就生成了。

Looper是跟一个线程关联的。而主线程会自动调用prepareMainLooper生成自己的Looper,

我们在Hander handler=new Handler();其实就已经把主线程的Looper关联上来了,

有了Looper我们也就有了MessageQueue 所以我们在调用sendMessage的时候就把这个Message发送到由Looper创建的MessageQueue里。

Looper有主线程创建的,当然消息会在主线程处理了。这样就实现了简单的子线程到主线程的通信了。

那好,如果现在我要创建子线程的Looper呢 然后怎么把这个Looper绑定Handler上呢。其实很简单 在子线程调用Looper.prepare()就可以创建子线程的Looper 然后通过Looper.myLooper()就可以拿到这个Looper对象,最后就是把这个Looper 跟Handler绑定起来。其实在构建handler对象的时候我们除了默认无参构造方法,还有有参的构造方法,就是传Looper的。好了,这样就可以把Looper跟Handler绑定起来了。这样在主线程调用Handler.sendMessage就是把message发到子线程里来了。这样就实现主线程到子线程的通信了。以此类推各种样式的通信都是可以的。大家回去不妨试一下。

================================================

开辟的线程怎样与UI主线程互相协调工作呢,这就得需要用到Handler了。

UI主线程里初始化时自动调用prepareMainLooper生成自己的Looper,并且自带一个消息队列(MessageQueen)。

Looper就像一个管道工,主要作用是循环迭代MessageQueen,加入新的Message,轮到这条消息时再发送出去。

而Handler就像包工头,可以直接操作Looper,例如:

Handler mHandler = new Handler(Looper.getMainLooper);就是用mHandler对象控制UI主线程的Looper对象,也就是控制了MessageQueen。

Handler mHandler = new Handler(Looper.myLooper);就是控制当前线程(也可能是UI主线程)的MessageQueen。

Handler间接控制了各个线程的MessageQueen来实现主线程与子线程的相互通信,传递消息队列,分派任务等复杂工作。

Handler还有一个用处,就是缓和任务冲突。当UI急需更新但是任务却在繁忙状态时,为了避免被系统杀死,这时最好利用Handler发送简单消息通知UI主线程更新界面,UI主线程在运行时会在空闲时取出消息解析运行,这样就不会造成任务冲突了。但是这样也可能会造成界面看起来一卡一卡的,最好的办法还是开辟一个新的线程来分摊工作。

有些没有界面的任务比如Service运行时需要更新UI界面,例如弹出对话框(Dialog),那就得通过Handler来发送消息,通知UI线程更新界面,这样才能弹出对话框。


在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?

首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应。

而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。

HandlerThread顾名思义就是可以处理消息循环的线程,他是一个拥有Looper的线程,可以处理消息循环。

与其说Handler和一个线程绑定,不如说Handler是和Looper一一对应的。


注意:在UI线程(主线程)中:

mHandler=new Handler();

mHandler.post(new Runnable(){

      void run(){

       //执行代码...

    }

});

这个线程其实是在UI线程之内运行的,并没有新建线程。


常见的新建子线程的方法:

Thread thread = new Thread();或者HandlerThread thread = new HandlerThread("string");

在需要调用的地方,调用

thread.start();


评论

© UUTON | Powered by LOFTER