Android 高级工程师进阶 ~ 网易云课堂 学习笔记
【课程主题】Handler源码分析 - 手把手带你实现Handler机制核心架构
【课程大纲】
1.Handler源码分析
2.根据源码手写实现Handler核心机制
3.充分理解Handler机制的作用
戳此链接加入学习:https://url.163.com/Ngk
Handler源码分析
1,什么是 Handler
Android SDK 中用来处理异步消息的核心类
子线程可以通过Handler 来通知主线程进行UI更新
Handler 机制核心类
Handler
Looper
轮询器 ,不断去消息队列中查询消息 发生到 线程中去
Message
在整个消息处理机制中,Message 又叫 Task ,封装了任务携带的信息和处理该任务的Handler,有这么几点需要注意:
(1)尽管Message 有 Public的默认构造方法,但是你应该通过Message.obtain() 来从消息中获得空消息对象,以节省资源。
(2) Message如果只需要携带 简单的 int 信息 ,请优先 使用 arg1 和 arg2 来传递消息,这比使用 Bundle 更省内存。
MessageQueue
消息队列
入队
Handler.sendMessage -> queue.enqueueMessage
出队
Looper.loop -> queue.next
Handler
MessageQueue mQueue
Looper mLooper
ThreadLocal 线程的数据隔离
根据源码手写实现Handler核心机制
直接撸代码
1, Handler 类
package com.example.handlerlib;
public class Handler {
private MessageQueue mQueue;
private Looper mLooper;
public Handler() {
//获取主线程的Looper对象
mLooper = Looper.myLooper();
this.mQueue = mLooper.mQueue;
}
/**
* 发生消息,压人队列
*/
public void sendMessage(Message msg) {
msg.target = this;//将Handler 绑定到msg 的 target
mQueue.enqueueMessage(msg);
}
public void handleMessage(Message msg) {
}
public void dispatchMessage(Message msg) {
handleMessage(msg);
}
}
2,Looper 类
package com.example.handlerlib;
public final class Looper {
/**
* 每一个主线程都会有一个Looper对象
* Looper对象 保存在ThreadLocal,保证子线程数据隔离
*/
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
// 有一个对应的消息队列
MessageQueue mQueue;
private Looper() {
mQueue = new MessageQueue();
}
/**
* Looper 对象的初始化
*/
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
/**
* 获取当前Looper对象
*
* @return
*/
public static Looper myLooper() {
return sThreadLocal.get();
}
/**
* 轮询消息队列
*/
public static void loop() {
Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread");
}
MessageQueue queue = me.mQueue;
for (;;){
Message msg = queue.next();
if (msg == null){
continue;
}
// 转发给Target 即Handler
msg.target.dispatchMessage(msg);
}
}
}
3,Message 类
package com.example.handlerlib;
public class Message {
Handler target;
public int what;
public Object obj;
@Override
public String toString() {
return obj.toString();
}
}
4,MessageQueue 类
package com.example.handlerlib;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MessageQueue {
// 通过数组的结构存储 Message 对象
Message[] items;
//入队与出队的元素的索引位置
int putIndex;
int takeIndex;
//计数器
int count;
private Lock lock;
//条件变量
private Condition notEmpty;
private Condition notFull;
public MessageQueue() {
//消息队列应该有大小限制
this.items = new Message[50];
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
this.notFull = lock.newCondition();
}
/**
* 加入队列
*
* @param msg
*/
public void enqueueMessage(Message msg) {
try {
lock.lock();
//消息队列满了,子线程停止发送消息 阻塞
while (count == items.length) {
try {
notFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
items[putIndex] = msg;
//循环取值
putIndex = (++putIndex == items.length) ? 0 : putIndex;
count++;
//有新的Message 对象,通知主线程
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
/**
* 出队
*
* @return
*/
public Message next() {
Message msg = null;
try {
lock.lock();
//如果消息队列是空的,,主线程looper 停止轮询
while (count == 0){
try {
notEmpty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
msg = items[takeIndex];//取出
items[takeIndex] = null;//元素置空
//循环取值
takeIndex = (++takeIndex == items.length) ? 0 : takeIndex;
count--;
//使用了一个Message 对象,继续生产
notFull.signalAll();
} finally {
lock.unlock();
}
return msg;
}
}
5,测试类
package com.example.handlerlib;
import java.util.UUID;
public class HandlerTest {
public static void main(String[] args) {
// 轮询器初始化
Looper.prepare();
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
System.out.println(Thread.currentThread().getName() + ",received:" + msg.toString());
}
};
// 子线程发生消息
for (int i = 0; i < 10; i++) {
new Thread() {
@Override
public void run() {
while (true) {
Message message = new Message();
message.what = 1;
synchronized (UUID.class){
message.obj = Thread.currentThread().getName() + " ,send Message:" + UUID.randomUUID().toString();
}
System.out.println(message);
handler.sendMessage(message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
Looper.loop();
}
}
源码地址
https://github.com/yoyo0316/StudyDemo/commit/23b2583ccf276554f83100d5aa62dafecffc9766