在了解Handler原理的同时可以翻看源码研究一下Handler架构,下面是本人手写的Handler架构
Message.java
public class Message { int what; Handler target; }
Message类我写的很简单,源码中是有很多代码的,这里能够传递值的参数只有what。target对象主要是为了最终能够执行到handleMessage回调方法,具体作用可以在下文代码中可以看到。
MessageQueue.java
/** * 互斥队列的通用类 */public class MessageQueue { //声明阻塞队列 private BlockingDeque blockingDeque = new LinkedBlockingDeque(50); /** * 入队(生产者) * @param msg * @return */ public void enqueueMessage(Message msg) { if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); } try { blockingDeque.put(msg); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 出队(消费者) * @return */ public Message next() { Message msg = null; try { msg = (Message) blockingDeque.take(); } catch (InterruptedException e) { e.printStackTrace(); } catch (Exception e){ e.printStackTrace(); } return msg; } }
MessageQueue类其实是最核心的地方了,这是一个消息队列,只有两种行文,出队和入队。并且,这是一个生产者、消费者设计模式。BlockingDeque是阻塞队列,在生产者、消费者设计模式中的运用比较常见。
Looper.java
public class Looper { static MessageQueue mQueue; private static ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 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()); } public static Looper myLooper() { return sThreadLocal.get(); } public static void loop(){ for(;;){ Message msg = mQueue.next(); if(msg == null){ continue; } msg.target.dispatchMessage(msg); } } }
Looper中含有一个消息队列,looper只负责一个任务,那就是无限遍历消息队列,如果队列中有消息,就从队首取出消息,传递给handleMessage回调方法。这里的dispatchMessage方法就是为了执行Handler的回调方法handleMessage。
Handler.java
public class Handler { private MessageQueue mQueue; public Handler() { Looper.prepare(); Looper looper = Looper.myLooper(); mQueue = looper.mQueue; } public void handleMessage(Message msg) { } public void dispatchMessage(Message msg){ handleMessage(msg); } public void sendMessage(Message msg){ MessageQueue queue = mQueue; if (queue != null) { enqueueMessage(queue, msg); } } private void enqueueMessage(MessageQueue mQueue, Message msg){ msg.target = this; mQueue.enqueueMessage(msg); } }
Handler负责将消息放进消息队列中,也就是所谓了入队了,sendMessage方法就是让消息入队。
Test.java
public class Test { private static Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); System.out.println(String.valueOf(msg.what)); } }; public static void main(String[] args){ new Thread(new Runnable() { @Override public void run() { for(int i=0;i<100;i++){ Message message = new Message(); message.what = i; handler.sendMessage(message); } } }).start(); Looper.loop(); } }
Looper.loop()这个方法不能放入Activity的UI线程,否则会阻塞,这里我新建一个java的启动入口, 我们只需要执行main方法就可以了。
在底层中,ActivityThread是UI线程, Android的启动入口就是这个类的main方法,main方法中已经声明了Looper
Looper.prepareMainLooper();Looper.loop();
图片.png
作者:NoBugException
链接:https://www.jianshu.com/p/92c8495c6ab1
共同学习,写下你的评论
评论加载中...
作者其他优质文章