Android Handler机制
来源:互联网 发布:饮料铺货软件 编辑:程序博客网 时间:2024/06/15 05:31
所有对象:
Handler、Looper、MessageQueue、Message和 用于存储当前线程的Looper对象的ThreadLocal.
对象间关系:
- ActivityThread在初始化时,在UI线程中调用Looper.prepare(),Looper.loop(),使UI线程中可以使用Handler对象。
- Looper中持有MessageQueue对象,即MessageQueue绑定在Looper中。
- handler在创建的时候,获取了当前线程的Looper对象,和绑定在Looper上的MessageQueue对象。
- handler通过sendMessageAtTime(msg)方法,调用了queue.enqueueMessage()将该message对象根据when插入到queue中。
- looper.loop()方法是一个for(;;)循环,不断调用MessageQueue.next()方法获取message对象。
- message中引用handler对象。在message被处理时,使用该msg.target.dispatchMessage(msg)方法将该message分发到创建该message的handler中处理。这样就通过handler可以使得信息在线程中传递。
特别注意
- ThreadLocal存储当前当前线程的Looper对象,作为线程局部变量可以被该线程内任何地方获取到。ThreadLocal作为static final对象被所有Looper对象共享。(可参考上篇 )
- 使用Handler的线程必须是Looper线程,否则抛出异常(构造方法中);或者是NullPointerException。
mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); }
- 一个线程只能调用一次Looper.prepare()。否则会抛出异常(prepare方法中):
if (sThreadLocal.get() != null) {//当前线程已经创建了Looper throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));
- handler是对外暴漏的,线程间可以互相调用handler发消息。只要持有不同的handler可以。
各个类详解:
Handler
- handler的创建方式可以传入Looper对象,即表明该handler是属于哪个线程的,即会回调到哪个线程来处理该message。以下实例为创建UI线程的handler。该技巧可以在其他线程中创建主线程的handler,用于回调到主线程中。
private Handler handler = new Handler(Looper.getMainLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { return true; } });
Message:
- Message类使用对象池模式。主要是使用Message.Obtain()中复用上一个Message,赋值比创建对象快的多。While the constructor of Message is public, the best way to get one of these is to call Message.obtain() or one of the Handler.obtainMessage() methods, which will pull them from a pool of recycled objects.
- 在Looper.loop()方法中,该message被分发到handler中使用完后,会调用msg.recycleUnchecked()方法进行回收。
//Looper.loop()中对每个message都调用msg.recycleUnchecked();void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
MessageQueue:
- 它主要包含两个操作,插入(enqueueMessage)和读取(next)。
- MessageQueue是链表结构,由Message.next()记录。其mMessages是该链表的header,由此来进行的next操作,在equeueMessage()方法中对所有message进行排列。
- next()作用是从消息队列中取出一条消息并将其从消息队列中移除。其中,nativePollOnce(ptr, nextPollTimeoutMillis)调用native方法阻塞线程。和Linux底层相关。
Looper:
- 每一个线程调用了Looper.prepare()后都有一套handler体系,调用Looper.prepare(),Looper.loop()就可以使用该线程的handler。(android提供了一个HandlerThread。IntentService使用之。)
- Looper是可以退出的。提供了quit()和quitSafely()两个方法。其中quitSafely()指把消息队列中的已有消息处理完毕后才安全退出。如果创建了一个looper子线程,必须要在所有事情完成以后退出该Looper.
使用技巧:
- Message类中持有handler引用,被调用后使用msg.target.dispatchMessage()方法将该msg返回给该handler,甚为精妙,之后若遇到这种转一大圈的需求可以用这种设计尝试。
- 在子线程中创建主线程的handler,持有主线程View,可以直接使用handler.post()方法修改该View的UI效果。在UniversalImageLoader中有很好的体现。
参考:
handler native源码分析
对象池设计模式
Message对象池设计模式
0 0
- Android笔记--handler机制
- android handler机制
- android handler机制
- android handler机制
- Android的Handler机制
- Android Handler机制
- Android Handler机制
- Android笔记--handler机制
- Android笔记--handler机制
- Android handler机制
- Android Handler机制
- Android中的Handler机制
- Android Handler机制
- android 的handler 机制
- Android Handler机制
- Android Handler机制详解
- Android中的Handler机制
- android Handler机制
- 面试笔试杂项积累-leetcode 331-335
- 阿里2015校招前端方向的一道面试题
- Linux内核编码风格
- notepad++更换添加主题
- 反射实现AOP动态代理
- Android Handler机制
- Git代码管理的使用流程
- Qualcomm Flight--首套四轴飞行器集成开发平台问世
- 欢迎使用CSDN-markdown编辑器
- java关键字transient native synchronized final
- pthhon连接数据库的中文乱码问题解决方案
- java 项目转化为maven的web项目
- springmvc接口参数如何解析
- Android开发规范文档