本文基于Android 6.0的源代码,来分析Handler的用法
framework/base/core/java/andorid/os/HandlerThread.java
一、实例
Android消息机制1, Android消息机制2 这两篇文章已经分别从Java和Native角度讲解了消息机制,那么对于Handler的用法,往往是在一个线程中运行Looper,其他线程通过Handler来发送消息到Looper所在线程,这里涉及线程间的通信。
下面列举两种创建Handler线程的实例
1.1 利用HandlerThread创建
既然涉及多个线程的通信,会有同步的问题,Android为了简化Handler的创建过程,提供了HandlerThread类, 很多时候,在HandlerThread线程中运行Loop()方法,在其他线程中通过Handler发送消息到HandlerThread线程。通过wait/notifyAll的方式,有效地解决了多线程的同步问题。
示例代码:
// Step 1: 创建并启动HandlerThread线程,内部包含Looper
HandlerThread handlerThread = new HandlerThread("gityuan.com");
handlerThread.start();
// Step 2: 创建Handler
Handler handler = new Handler(handlerThread.getLooper());
// Step 3: 发送消息
handler.post(new Runnable() {
@Override
public void run() {
System.out.println("thread id="+Thread.currentThread().getId());
}
});
或者 handler.postDelayed(Runnable r, long delayMillis)用于延迟执行。
2.2 直接创建线程
示例代码:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
// Step 1: 创建Handler
mHandler = new Handler() {
public void handleMessage(Message msg) {
//处理即将发送过来的消息
System.out.println("thread id="+Thread.currentThread().getId());
}
};
Looper.loop();
}
}
// Step 2: 创建并启动LooperThread线程,内部包含Looper
LooperThread looperThread = new LooperThread("gityuan.com");
looperThread.start();
// Step 3: 发送消息
LooperThread.mHandler.sendEmptyMessage(10);
二、HandlerThread源码实现
这里还在看看HandlerThread的源码实现
1.1 创建HandlerThread对象
HandlerThread 继承于Thread类
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT; //默认优先级
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
1.2 获取Looper对象
获取HandlerThread线程中的Looper对象
public Looper getLooper() {
// 当线程没有启动或者已经结束时,则返回null
if (!isAlive()) {
return null;
}
//当线程已经启动,则等待直到looper创建完成
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait(); //休眠等待
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
1.3 执行HandlerThread的run()
public void run() {
mTid = Process.myTid(); //获取线程的tid
Looper.prepare(); // 创建Looper对象
synchronized (this) {
mLooper = Looper.myLooper(); //获取looper对象
notifyAll(); //唤醒等待线程
}
Process.setThreadPriority(mPriority);
onLooperPrepared(); // 该方法可通过覆写,实现自己的逻辑
Looper.loop(); //进入循环模式
mTid = -1;
}
1.4 Looper退出
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;
}
quit()与quitSafely()的区别,仅仅在于是否移除当前正在处理的消息。移除当前正在处理的消息可能会出现不安全的行为。