Android(安卓)Handler 机制
参考文章:
深入理解Handler机制
Android 事件机制详解
Android Handler消息机制的理解
android的消息处理机制(图+源码分析)——Looper,Handler,Message
概述
在开发中,Handler通常用于异步消息处理,相关联的类有:
ThreadLocal、Looper、MessageQueue、Message、Handler.
Handler持有MessageQueue和Looper,而Looper持有持有MessageQueue,Message中包含Handler和Runnable成员变量。
其中
- ThreadLocal是把新创建的Looper对象设置进线程本地存储区里。
- Looper在后台不断轮询获取Message,后调用msg.target.dispatchMessage()执行,最终会掉用handler的handleMessage()。
- MessageQueue是一个连表结构的集合。里面装有多个Runnable、Message对象
- Message类似一个JavaBean,其中包含了消息ID,消息处理对象CallBack以及处理的数据Message.obj等
- Handler是一个调度器,发送消息会掉用enqueueMessage方法将消息打入MessageQueue,
在一个线程中通过调用Looper.prepare();初始化即可使线程成为Looper线程,通过Looper.loop() 来循环处理消息队列
ThreadLocal
参考资料:解密ThreadLocal
正确理解ThreadLocal
ThreadLocal提供了线程局部变量,在线程的生命周期内起作用,使得各线程能够保持各自独立的一个对象,在Thread中将new出来的对象通过ThreadLocal.set()来设置独立于其他线程的对象,其他线程不可访问,不是用来解决线程同步问题的。
每个线程中都有一个ThreadLocalMap类对象,而ThreadLocal实例就是key,value是真正需要存储的Object,在Android’Handler机制中就是我们的Looper对象。
public final class Looper { private static final String TAG = "Looper"; // sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; final Thread mThread; private Printer mLogging;//....
Looper
通过Looper.prepare();来初始化Looper,并将Looper对象存储到本地线程中,而后创建Handler对象,并掉用Looper.loop()方法进行轮询。
注意:一个线程可以有多个Handler,每个线程中只有一个Looper对象。
public static void prepare() { prepare(true);}private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); // 创建Looper对象,并设置进TLS}//.....
Looper.loop()
public static final void loop() { Looper me = myLooper(); //得到当前线程Looper MessageQueue queue = me.mQueue; //得到当前looper的MQ Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); // 开始循环 while (true) { Message msg = queue.next(); // 取出message if (msg != null) { if (msg.target == null) { // message没有target为结束信号,退出循环 return; } //... // 将真正的处理工作交给message的target,即发送消息的handler msg.target.dispatchMessage(msg);
Handler
首先,来看一下handler 的构造函数,
public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper();// 设置looper if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; //设置MessageQueue mCallback = callback; //设置CallBack mAsynchronous = async; }
Handler对象在构造时,不但会把Looper对象记录在它内部的mLooper成员变量中,还会把Looper对象的消息队列也一并记录
public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
handler中的post 和send方法都会最终调用sendMessageAtTime方法,通过enqueueMessage方法将消息压入MessageQueue中
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; // message的target必须设为该handler! sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
Handler.dispatchMessage()
这个方法是有Looper.loop()方法调用。
public void dispatchMessage(Message msg) { if (msg.callback != null) { // 如果message设置了callback,即runnable消息,处理callback! handleCallback(msg); } else { // 如果handler本身设置了callback,则执行callback if (mCallback != null) { /* 让activity等来实现Handler.Callback接口,避免了自己编写handler重写handleMessage方法。*/ if (mCallback.handleMessage(msg)) { return; } } // 如果message没有callback,则调用handler的钩子方法handleMessage handleMessage(msg); } } // 处理runnable消息 private final void handleCallback(Message message) { message.callback.run(); //回调CallBack中的run方法! } // new Handler的时候需要实现的方法 public void handleMessage(Message msg) { }
更多相关文章
- Android(安卓)MapView 申请apiKey
- android handler
- Android的线程使用来更新UI----Thread、Handler、Looper、TimerT
- Android主线程里不允许网络操作
- android时序图 以及UML中时序图、流程图、状态图、协作图之间的
- android中在子线程中更新UI的几种方法
- Android(安卓)基础UI编程1
- Android(安卓)颜色渲染(十) ComposeShader组合渲染
- android的多线程操作(一)