从另一种方式理解Android消息处理机制
事件驱动线程
网上大把的资料都在说Android事件分发机制,什么Handler,Looper,我们也看了N+1遍了,面试也考了N+1次了。所以,我们对Handler的使用也是轻车熟路了。竟然那么简单,那么,接下来我们就来一起实现它。
* class LooperThread extends Thread { * public Handler mHandler; * * public void run() { * Looper.prepare(); * * mHandler = new Handler() { * public void handleMessage(Message msg) { * // process incoming messages here * } * }; * * Looper.loop(); * }
执行完上面的伪代码后,我们的线程就变成了事件驱动线程,就是,我们发送一个事件,他才会工作,否则就会堵塞。这里用LinkedBlockingQueue来当作MessageQueue,并且LinkedBlockingQueue内部也是用链表实现的,只不过是双端链表,为了尽可能简单化…
实现
1、Message
public final class Message implements Serializable{ private Object obj; private Handler mHandler; public Object getObj() { return obj; } public void setObj(Object obj) { this.obj = obj; } public Handler getmHandler() { return mHandler; } public void setmHandler(Handler mHandler) { this.mHandler = mHandler; }}
这个没什么好说的,比较简单。
2、Looper
public final class Looper { static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); final LinkedBlockingQueue<Message> mQueue; private static Logger logger = Logger.getLogger("Looper"); private Looper() { mQueue = new LinkedBlockingQueue<Message>(); } public static void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); logger.info("Prepare...."); } public static Looper myLooper() { return sThreadLocal.get(); } public static void loop(){ final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final LinkedBlockingQueue<Message> queue = me.mQueue; logger.info(queue==null?"没有获取到MessageQueue":"获取到了MessageQueue"); while(true){ try{ Message message = null; try { message = queue.take(); logger.info(message == null?"没有消息取出":"有消息取出"); } catch (InterruptedException e) { e.printStackTrace(); } if(message != null){ message.getmHandler().dispatchMessage(message); logger.info("处理消息..."); } }catch(Exception e){ e.printStackTrace(); } } }}
当某个线程调用我们prepare()方法的时候,我们就会为它本地生成一个Looper对象,并且初始化一个MessageQueue,当入队列的时候,就是根据Looper对象找到MessageQueue的。当调用loop()方法的时候,Looper就开始一直轮循了,其中take()是一个堵塞方法,没有Message进入MessageQueue就一直堵塞。然后从Message中找到调用他的Handler,然后通过Handler分发消息。接下来的是Handler
3、Handler
public class Handler { private CallBack callback; private Looper mLooper; private LinkedBlockingQueue<Message> mQueue; public Handler() { // TODO Auto-generated constructor stub mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; } public Handler(CallBack callback) { mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; this.callback = callback; } public Handler(Looper looper, CallBack callback) { mLooper = looper; mQueue = looper.mQueue; this.callback = callback; } public interface CallBack{ boolean handleMessage(Message msg); } public void handleMessage(Message msg) { } public void dispatchMessage(Message msg) { if (callback != null) { if (callback.handleMessage(msg)) { return; } } msg.getmHandler().handleMessage(msg); } public void sendMessage(Message msg){ if(msg != null){ msg.setmHandler(this); } if(mQueue != null){ try { mQueue.put(msg); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
Handler的生成很重要,如果无参的话,就要和Looper.prepare()同一个线程中生成,否则,就要自己传入looper,让Handler把消息丢入指定的队列中,因为上面Looper的分析可知,每个线程中维护了一个Looper对象,每个Looper对象又维护了一个MessageQueue对象。还有,在sendMessage()入队列的时候,要把自己传入给Message对象,等到处理的时候,就可以知道是谁调用的了,是谁调用的,就让谁处理。当然,我们也可以在构造Handler对象的时候,传入一个CallBack 对象,这样就不会默认执行handleMessage()方法了,就是我们实现CallBack接口的方法了。好的,下面来运行下,看看效果。
4、实现效果
public class Test { private static Handler mHandler; public static void main(String[] args) { new Thread(){ public void run() { Looper.prepare(); mHandler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); if(msg != null){ System.out.println(msg.getObj()); } } }; Looper.loop(); }; }.start(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message msg = new Message(); msg.setObj("消息处理机制~"); mHandler.sendMessage(msg); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message msg1 = new Message(); msg1.setObj("消息处理机制~"); mHandler.sendMessage(msg1); }}
下面是打印信息:
更多相关文章
- Android 更新UI 只能在主线程?
- android 之对象传递
- android 消息机制与仿新闻客户端
- Android之Handler消息机制
- Android 并发工具类与线程池
- Android中Intent对象与Intent Filter过滤匹配过程详解
- android中的进程与线程
- Android线程处理简述