android 自定义looper,Android-Handler机制详解并自定义Handler

之前研究过Android的Handler机制,但是一直没有机会自己实现一次。最近又看到这个Handler机制,于是决定自己实现以下这个Handler机制。

首先,简单介绍以下Handler机制。

Handler机制在Android中通常用来更新UI:子线程执行任务,任务执行完毕后发送消息:Handler.sendMessage(),然后在UI线程Handler.handleMessage()就会调用,执行相应处理。

Handler机制有几个非常重要的类:

Handler:用来发送消息:sendMessage等多个方法,并实现handleMessage()方法处理回调(还可以使用Message或Handler的Callback进行回调处理,具体可以看看源码)。

Message:消息实体,发送的消息即为Message类型。

MessageQueue:消息队列,用于存储消息。发送消息时,消息入队列,然后Looper会从这个MessageQueen取出消息进行处理。

Looper:与线程绑定,不仅仅局限于主线程,绑定的线程用来处理消息。loop()方法是一个死循环,一直从MessageQueen里取出消息进行处理。

原理图如下:

9453822149b1d6d6e04b0f502269c8c5.png

按照上面介绍的4个重要组成类,从内向外依次自定义相应的类,实现Handler机制。

MyMessage类:

public class MyMessage {

private int code;

private String msg;

MyHandler target;

public MyMessage(int code, String msg) {

this.code = code;

this.msg = msg;

}

public int getCode() {

return code;

}

public void setCode(int code) {

this.code = code;

}

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

}

MessageQueue类:(由于该类可以有多种实现方式,所以在此定义一个接口)

public interface IMyMessageQueue {

MyMessage next() throws InterruptedException;

void enqueueMsg(MyMessage msg) throws InterruptedException;

}

从Android源码中了解到,这个MessageQueue是一个队列,所以在此简单的已一个BlockingQueue队列来实现消息的进队出队操作:

public class MyBlockingQueue implements IMyMessageQueue {

private BlockingQueue mQueue;

public MyBlockingQueue(int init) {

this.mQueue = new LinkedBlockingDeque<>(init);

}

@Override

public MyMessage next() throws InterruptedException {

return mQueue.take();

}

@Override

public void enqueueMsg(MyMessage msg) throws InterruptedException {

mQueue.put(msg);

}

}

MyLooper类:持有一个MyMessageQueue实例,并使用ThreadLocal绑定当前线程,启动一个死循环。

public class MyLooper {

private static final ThreadLocal THREAD_LOCAL = new ThreadLocal<>();

IMyMessageQueue mMessageQueue;

private static MyLooper mMainLooper;

public MyLooper() {

mMessageQueue = new MyBlockingQueue(4);

}

public static void prepare() {

if (null != THREAD_LOCAL.get()) {

throw new RuntimeException("Only one looper can be created per thread.");

}

THREAD_LOCAL.set(new MyLooper());

}

public static void prepareMainLooper() {

prepare();

synchronized (MyLooper.class) {

if (null != mMainLooper) {

throw new RuntimeException("MainLooper has already been prepared.");

}

mMainLooper = myLooper();

}

}

public static void loop() {

final MyLooper looper = myLooper();

if (null == looper) {

throw new RuntimeException("No looper! MyLooper.prepare() wasn't called on this thread.");

}

for (; ; ) {

MyMessage msg = null;

try {

msg = looper.mMessageQueue.next();

} catch (InterruptedException e) {

e.printStackTrace();

}

if (null != msg) {

msg.target.handleMessage(msg);

}

}

}

public static MyLooper getMainLooper() {

return mMainLooper;

}

public static MyLooper myLooper() {

return THREAD_LOCAL.get();

}

}

MyHandler类:持久消息队列,并定义一个抽象方法,负责发送和处理消息。

public abstract class MyHandler {

private IMyMessageQueue mQueue;

public MyHandler(MyLooper looper) {

mQueue = looper.mMessageQueue;

}

public MyHandler() {

MyLooper.myLooper();

}

public void sendMessage(MyMessage msg) {

msg.target = this;

try {

mQueue.enqueueMsg(msg);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public abstract void handleMessage(MyMessage msg);

}

到此,自定义Handler功能代码实现,下面测试一下启动MyMainLooper,并在子线程中使用MyHandler发送和处理消息。

TestMyHandler

public class TestMyHandler {

@Test

public void test() {

MainThread mainThread = new MainThread();

mainThread.start();

while (null == MyLooper.getMainLooper()) {

try {

Thread.sleep(20);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

MyHandler handler = new MyHandler(MyLooper.getMainLooper()) {

@Override

public void handleMessage(MyMessage msg) {

switch (msg.getCode()) {

case 1:

System.out.print(msg.getMsg() + "在" + Thread.currentThread().getName() + "上执行!\r\n");

break;

case 2:

System.out.print(msg.getMsg() + "在" + Thread.currentThread().getName() + "上执行!\r\n");

break;

}

}

};

new Thread(() -> {

MyMessage myMessage = new MyMessage(1, "子线程消息1");

handler.sendMessage(myMessage);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

MyMessage myMessage2 = new MyMessage(2, "子线程消息2");

handler.sendMessage(myMessage2);

}).run();

}

/**

* 主线程

*/

public class MainThread extends Thread {

public MainThread() {

setName("MainThread");

}

@Override

public void run() {

MyLooper.prepareMainLooper();

System.out.print(getName() + "has been prepared.\r\n");

MyLooper.loop();

}

}

}

测试结果:

99a123ed1ea055085c069ce5e2b96810.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值