Android HandlerThread、Handler、Looper、MessageQueue、Message 简单分析

Message


Message implements Parcelable

public int what;//defined message code
public int arg1;
public int arg2;
public Object obj;
/*package*/ Handler target; 相关的外部调用方法 sendToTarget(){target.sendMessage(this);} 还有get/set方法
/*package*/ Bundle data; 相关的外部调用方法 Bundle peekData(); setData(Bundle data);
/*package*/ Runnable callback; 相关的外部调用方法 Runnable getCallback();
/*package*/ Message next;
private static Message sPool;

静态sPool,链表结构:每个对象都有一个next指针
一些重载的obtain():如果池中有对象,从sPool中取一个,并将当前指针指向下一个;如没有,则new Message();
obtain()中必须传一个Handler对象,赋给target

MessageQueue


简单的说就是 存放、获取Message的管理类
类本身的构造函数也是 package的访问权限,即外部不能new 一个它的实例对象
/*package*/ Message mMessages; //存储Message
主要方法:
enqueueMessage(Message, long);
新消息加入到mMessages的链尾
Message next();
取出链尾的最新消息,并改变指针指向
removeMessages()、removeCallbacksAndMessages(); 都要传入一个handler对象

Looper


消息循环

主要属性与构造方法源码:

static final ThreadLocal sThreadLocal = new ThreadLocal();
private static Looper sMainLooper;  // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread(); //关联当前调用者线程
}

主要方法:
private static void prepare();
加锁判断sMainLooper是否设置值:有,抛出异常;无,则 sThreadLocal.set(new Looper(…))
说明该方法仅能执行一次

public static void prepare();
调用私有prepare();

public static void prepareMainLooper();//ui线程,即main线程 使用
调用私有prepare();
加锁判断sMainLooper是否设置值:有,抛出异常;无,则 sMainLooper = myLooper();

public static Looper getMainLooper()
加锁,返回 sMainLooper

public static @Nullable Looper myLooper()
返回 sThreadLocal.get()

public static void loop()
在Looper所属的线程,开启消息循环。
通过myLooper(),拿到Looper对象,再获取它的MessageQueue对象。
启动一个无线循环:queue.next(),获取Message对象,再调用msg.target.dispatchMessage(msg);
即最后,调用Handler对象的dispatchMessage()

一般的使用方式,如下,

  • UI主线程使用:
    prepareMainLooper();静态sMainLooper被赋值,mThread=主线程

  • 子线程使用:
    prepare();由于sThreadLocal是一个线程局部变量,即使声明为static,在子线程中也是一个新的对象,可以由它set/get一个new Looper();这时sMainLooper还是主线程赋值的Looper对象,myLooper()才是子线程的Looper对象,mThread=子线程

Handler


统一处理前面所有消息相关元素。

主构造方法 :

public Handler(Looper looper, Callback callback, boolean async);
public Handler(Callback callback, boolean async);

这两个构造方法是@hide的,其它构造方法基于这两个方法。
关于Looper对象,没有手动指定时,默认直接从Looper.myLooper()获取;
那就需要在初始化Handler之前,就初始化一个Looper;
Android系统帮我们初始了主线程的Looper,在源码ActivityThread的入口main()中。
Callback定义:

public interface Callback {
    public boolean handleMessage(Message msg);
} 

async 表示是异步还是同步的处理消息,true为异步

一些操作Message的方法,如obtainMessage()系列、getPostMessage()系列、sendMessage()系列、removeMessages()系列;

一些操作Message#callback的方法,如post()系列、removeCallbacks()系列;
Looper getLooper();

public void handlerMessage(Message);
可以由子类重写,默认空实现

public void dispatchMessage(Message);
该方法是处理消息的总入口,一般不需要手动重写
判断msg的callback是否为空,不为空时执行msg.callback.run();
为空,再判断当前Handler对象的Callback实例属性,是否为空,不为空时执行mCallback.handleMessage(msg);
还为空,执行this.handlerMessage(msg);

由此看出这些元素执行的判断优先级:msg.callback > mCallback.handlerMessage() > this.handlerMessage()
Handler通常我们用的new Handler()默认,是处理同步消息的。如果要处理的是异步消息,需谨慎

HandlerThread


HandlerThread extends Thread

主要的方法源码 {

protected void onLooperPrepared() { }
public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    public boolean quit() {//关闭消息循环
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
    public boolean quitSafely() {//安全的关闭消息循环
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }
    public Looper getLooper() { ... }
}

这是一个Thread的子类;run()中,初始了Looper,并开启了消息循环;还提供了关闭消息循环的方法。

使用场景:如果要在子线程中使用Handler传递消息,可以继HandlerThread。通过getLooper获取Looper,并传递给Handler对象。

如果要在开启消息循环即Looper.loop()之前,处理某些事,可以重写onLooperPrepared(),比如初始化一个Handler:

protected void onLooperPrepared() {
    mHandler = new Handler() {
        public void handleMessage(Message msg) {

        }
    };
}

你可能感兴趣的:(Java)