您的位置:首页 > 产品设计 > UI/UE

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

2017-07-03 16:53 387 查看

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<Looper> sThreadLocal = new ThreadLocal<Looper>();
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) {

}
};
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐