面试系列:handler 运行机制理解

最近面试就常问的一些问题做一些笔记

handler消息机制在android中使用度很高,最常用的UI线程的更新,一些循环操作的逻辑(比如我项目中循环播放广告),使用的地方很广,下面我就简单介绍一下机制。

主要内容

handler包括三大部分 :Handler、MessageQueue、Looper,这里简单的流程是通过Handler发送消息发到MessageQueue中,并由Looper取出消息处理。

其中MessageQueue虽然叫做消息队列,但是其实内部存储结构是一个单链表。

其中Looper是扮演轮询器不断的查看MessageQueue中并取出数据来进行处理,如果没有消息需要处理的时候会一直阻塞在那里。

如何创建一个Looper呢?

Looper.prepare();//并且在创建Looper的时候也会初始化MessageQueue

MessageQueue的初始化是在Looper的构造函数句进行的,代码如下:

 private Looper (boolean quitAllowed){
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

介绍完概念下面如何在创建并开启一个循环呢?

new Thread("myThread"){
@Override
public void run(){
        Looper.prepare();//如果不创建Looper,就创建handler会报错。
        Handler handler =  new Hadnler();
        Looper.loop();
    }

}

注意事项:

Looper是提供了退出的方法,分别为quit和quitSafely方法,主要区别是quitSafely会先设置一个标记,在将队列里的方法都执行完才会退出。如果不调用退出的方法子线程会一直处于等待的状态。

Looper.loop();方法执行过程分析?

该方法是一个死循环,唯一跳出循环的方式是调用MessageQueue的next();方法返回null。当Loop的quit方法被调用,就会调用到MessageQueue的quit或者quitSafely方法标记退出,这时 候在调用next();方法机会返回null,停止这个循环。

所以当Looper不在使用的时候要求退出,否则loop()方法会无限循环下去,不断调用next方法,如果没有消息next会阻塞在那里,导致loop()方法也会一直阻塞在那里。

Handler的工作原理?

Handler主要是发送消息到MessageQueue中,然后MessageQueue在通过next方法返回消息给Looper,然后Looper在把消息交给发送消息的Handler自身来处理,完成一个在某一个线程的消息循环。

Handler消息处理过程?

入口方法是dispatchMessage(Message message){}

  • 首先检查Message的callback方法是否为null,不为null就通过handleCallback来处理消息。Message的callback是一个runnable对象,实际上就是handler的post方法所传递的runnable对象。
  • 其次检查mCallback是否为null,不为null就调用mCallback的handlerMessage方法来处理消息。通过Callback可以采取如下方式创建handler对象:Handler handler = new Handler(callback);Callback的意义在于,可以用来创建一个handler的实例,但不不需要派生Handler的子类。 一般日常开发都是派生一个Handler并重写handlerMessage方法来处理具体的消息,而Callback给我们提供来另一种Handler使用方式。
  • 最后调用Handler的handlerMessage方法来处理消息。

流程图(有道云笔记)

graph TD
    a[开始]-->b{msg.callback!=null}
    b-->|Y|c[handleCallback]
    b-->|N|d{mCallback!=null}
    d-->|Y|e{"mCallback.handlerMessage(msg)==true"}
    d-->|N|f["handlerMessage(msg)"]
    e-->|Y|g
    f-->g
    c-->g[结束]

面试系列:handler 运行机制理解_第1张图片

介绍主线程的消息循环机制

Android的主线程就是ActivityThread,主线程的入口方法为main方法。在main方法中会调用初始化Looper.preMainLopper();创建主线程的Looper和MessageQueue并通过Looper.loop();开启消息循环。
开启循环后还需要一个主线程的Handler来发送和处理消息。这个handler就是ActivtyThread.H,其内部定义了一些四大组件开启和停止的消息。

目前就介绍上面内容。

你可能感兴趣的:(面试问题)