1、分析handler原理
主线程和子线程通信通常靠Handler,要实现通信,需要Handler、MessageQueue、Message、Looper
用图表示
每个Handler都有一个Looper对象,而Looper对象的生成过程是
//sThreadLocal.get() will return null unless you've called prepare()
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<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对象是保存在ThreadLocal当中。
ThreadLocal用于线程间的数据隔离,保证数据安全。
给当前线程关联一个Looper对象。
sThreadLocal.set(new Looper());
在android程序的入口ActivityThread中,默认为主线程关联了一个Looer对象,所以在调用Handler时,我们不用自己给主线程关联Looper对象,也就是Looper.prepare()
ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
Looper.loop()
}
Looper.java中
public static void prepareMainLooper() {
prepare();
...
}
2、模范Handler实现主/子线程通信
新建Handler.java
package com.handler;
/**
* Created by Tony on 2017/6/11.
*/
public class Handler {
private MessageQueue mQueue;
//Handler的初始化在主线程中完成
public Handler() {
//获取主线程的Looper对象
this.mQueue = Looper.myLooper().mQueue;
}
/**
* 发送消息,压入队列
* @param msg
*/
public void sendMessage(Message msg) {
msg.target = this;
mQueue.enqueueMessage(msg);
}
public void dispatchMessage(Message msg) {
handleMessage(msg);
}
public void handleMessage(Message msg) {
}
}
新建Looper文件
package com.handler;
/**
* Created by Tony on 2017/6/11.
*/
public final class Looper {
//每一个主线程都有一个Looper对象
//Looper对象保存在ThreadLocal,保证了线程数据的隔离
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//一个Looper对象对应一个消息队列
MessageQueue mQueue;
private Looper() {
mQueue = new MessageQueue();
}
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("");
}
MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next();
if (msg == null) {
continue;
}
//转发给Handler
msg.target.dispatchMessage(msg);
}
}
}
新建MessageQueue
package com.handler;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by Tony on 2017/6/11.
*/
public class MessageQueue {
/**
* 消息队列应该要有大小限制
* 消息队列满了,子线程停止发送消息,阻塞
* 消息队列为空,主线程Looper停止轮循,阻塞
*/
//通过数组的结构存储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();
}
/**
* 入队列(子线程运行)
* @return
*/
public void enqueueMessage(Message msg) {
try {
lock.lock();
//消息队列满了,子线程挺好i发送消息,阻塞
while (count == items.length)
{
try {
notFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
items[putIndex] = msg;
//循环取值
putIndex = (++putIndex == items.length) ? 0:putIndex;
count++;
//有新的Message对象,通知主线程
notEmpty.signal();
} finally {
lock.unlock();
}
}
/**
* 出队列(主线程运行)
* @return
*/
public Message next() {
Message msg = null;
try {
//消息队列为空,主线程Looper停止轮询,阻塞
lock.lock();
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.signal();
} finally {
lock.unlock();
}
这里写代码片
新建Message.java
package com.handler;
/**
* Created by Tony on 2017/6/11.
*/
public class Message {
Handler target;
public int what;
public Object obj;
@Override
public String toString() {
return obj.toString();
}
}
return msg;
}
}
新建测试文件HandlerTest.java
package com.handler;
import java.util.UUID;
/**
* Created by Tony on 2017/6/12.
*/
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(new Runnable() {
@Override
public void run() {
while (true) {
Message msg = new Message();
msg.what = 1;
synchronized (UUID.class){
//加锁,线程安全
msg.obj = Thread.currentThread().getName() +",send message:"+ UUID.randomUUID().toString();
}
handler.sendMessage(msg);
System.out.println(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
//开始轮询
Looper.loop();
}
}
测试结果如下:
以上用了较简单的方式实现了主线程和子线程的通信。
本文详细解析了Android中Handler的工作原理,包括其内部结构如Looper、MessageQueue等,并通过自定义实现展示了主线程与子线程之间的通信流程。
645

被折叠的 条评论
为什么被折叠?



