Handler,MessageQueue,Message,Looper源码分析
来源:互联网 发布:手机网页小游戏源码 编辑:程序博客网 时间:2024/05/18 02:14
Handler机制源码分析
我的github博客详解
Handler 核心成员变量与方法:
MessageQueue,Message 核心成员变量与方法:
Looper 核心成员变量与方法:
Handler的工作原理涉及:Handler,MessageQueue,Message,Looper,ThreadLocal 等多个类
简单分析:
1,Handler初始化都做些什么?
2,Handler的常用几种方法有哪些?
3,Handler把Meesage发送到什么地方去了?
4,MessageQueue是什么,他与Handler,Message,Looper存在什么样的关系?
5,Message源码分析
6,Handler,Message,MessageQueue,Looper之间是怎么样工作的?
7,子线程也能使用Handler,MessageQueue,Looper机制吗?
开始分析:
1,Handler初始化都做些什么?
先看看Handler的构造函数
public Handler() { this(null, false); } public Handler(Looper looper) { this(looper, null, false); } 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(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
从上面可以看出,Handler有多个构造器。从代码最多的构造器看到,Handler初始化做了三件事:
1-1,获取到当前线程的Looper
mLooper = Looper.myLooper(); public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
1-2,获取当前Looper的消息队列MessageQueue
mQueue = mLooper.mQueue;
1-3,初始化callback
mCallback = callback;
2,Handler的常用几种方法有哪些?
public final Message obtainMessage() { return Message.obtain(this); } public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } public final void removeCallbacks(Runnable r) { mQueue.removeMessages(this, r, null); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
3,Handler把Meesage发送到什么地方去了?
当Handler调用sendMessage方法时,Handler会把Message放入到Looper的MessageQueue中。
值得注意的是,sendMessage时,Handler把自己对象引用也给Message,在Message成员变量target里
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
4,MessageQueue是什么,他与Handler,Message,Looper存在什么样的关系?
MessageQueue拥有Message作为成员变量,而Message类中存在Message next成员变量与静态的Meesage sPools变量,
这就意味着Message类中存在自己的对象,自己当中包含自己,形成了一条链表结构,不亚于数组的结构。
Handler把Message交给MessageQueue之后,MessageQueue把这个Message对象引用下来
boolean enqueueMessage(Message msg, long when) { if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle(); return false; } msg.markInUse(); msg.when = when; Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { // New head, wake up the event queue if blocked. msg.next = p; mMessages = msg;
可以看到最后一行,mMessages成员变量拿到了传递进来的message引用
而Looper存在一个成员变量就是MessageQueue,在Looper的loop方法中,从MessageQueue找出已存在的Message
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 MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long traceTag = me.mTraceTag; if (traceTag != 0) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } }
看到for循环里的第一行,从MessageQueue取出Message了
接下来看Looper怎么处理Message的?
看着一行代码:
msg.target.dispatchMessage(msg);
上面我们知道message的target就是Handler,绕了一圈,还是让Handler来处理这个Message,进入方法中:
/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } private static void handleCallback(Message message) { message.callback.run(); } public interface Callback { public boolean handleMessage(Message msg); } public void handleMessage(Message msg) { }
可以看到,首先判断message有没有callback,这个callback就是平时我们调用Handler.post(run)传递一个Runable对象回调的方法。
而mCallback是Handler内部的一个接口,也可以使用这个接口。最后才是回调handleMessage这个方法
最后,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++; } } }
5,Message源码分析
跟着Handler,sendMessage绕了一圈,路过MessageQueue,Looper,最后还是让Handler来处理这个Message。
那好,现在我们来研究一下这个Message
public final class Message implements Parcelable { public int what; public int arg1; public int arg2; public Object obj; /*package*/ int flags; /*package*/ long when; /*package*/ Bundle data; /*package*/ Handler target; /*package*/ Runnable callback; // sometimes we store linked lists of these things /*package*/ Message next; private static final Object sPoolSync = new Object(); private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 50;
先看Message源码中的成员变量:
what,arg1,arg2,这些是用来区分Message来使用的,一般只用what,这里告诉你:这三个都可以随便用
long when 是message执行的时间
Handler target 这是就是引用的Handler了,每一个Message都知道自己是被哪一个Handler来处理的
Runnbale callback 这就是post传递进去的Runnable对象,也被Message拿到了,
所以说,sendMessage和post最终都是以Message的形式来处理的
Message next 这是Message里包含下一个Message,形成了单链表结构
static Message sPool 这就是传说中的消息池了,没错他就是一个Message对象而已,静态的成员变量。
static final int MAX_POOL_SIZE = 50; google工程师限时这个消息池的最大长度,50个
接来看我们来研究Message如何创建和被回收的。
首先,创建Message:
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }
可以看出,如过消息池为空,直接new出来。否则直接去池里取一个Message对象,把下一个Message设置到池里,池数目减减
如果谁以后创建Message还自己手动New的话,我在这先鄙视一下…
当使用完毕之后,Message会被回收
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++; } } }
这里把Message的成员变量清空个遍,sPool = this ,这行就是把Message还回池中了,池数目加加
6,Handler,Message,MessageQueue,Looper之间是怎么样工作的?
1,创建Handler,Handler获取到当前线程的Looper,Looper里的MessageQueue
2,创建Message,是通过池是否有消息来返回Message的,池一个都没有才会new
3,sendMessage与post,本质都是Message,最后获取Handler引用,Message被传递给了MessageQueue
4,Looper的loop方法,检查Looper的MesaageQueue是否有Message,有的话把Message传递给Handler来处理
5,Message回收
7,子线程也能使用Handler,MessageQueue,Looper机制吗?
去看Looper源码头上的注释就知道了:
/** * Class used to run a message loop for a thread. Threads by default do * not have a message loop associated with them; to create one, call * {@link #prepare} in the thread that is to run the loop, and then * {@link #loop} to have it process messages until the loop is stopped. * * <p>Most interaction with a message loop is through the * {@link Handler} class. * * <p>This is a typical example of the implementation of a Looper thread, * using the separation of {@link #prepare} and {@link #loop} to create an * initial Handler to communicate with the Looper. * * <pre> * 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(); * } * }</pre> */ public final class Looper {
google工程师都把代码写给你了。闲麻烦的话,那就去用google工程师又帮你写好的HandlerThread这个类吧,
子线程使用Handler,Looper机制。
什么时候用子线程开启Handler,Looper机制呢,看需求吧。Handler机制拥有Message 50个消息队列,
能很好的保证处理的任务或者消息以线性的方式来执行,在子线程保证线性执行噢。
但是不能玩太耗时的操作,毕竟是队列。
分析就到这里了
11/8/2016 4:29:08 PM
- Handler源码分析,Handler,Looper,Message,MessageQueue
- (Handler+Message+Looper+MessageQueue)源码分析
- Handler,MessageQueue,Message,Looper源码分析
- 【安卓笔记】Handler,Looper,MessageQueue,Message源码分析
- Handler、Message、MessageQueue、Looper关系及源码分析
- Android 消息机制 - Handler, Looper, Message, MessageQueue 的源码分析
- Looper、Message、MessageQueue、Handler异步消息处理机制源码分析
- 从源码来分析ThreadLocal、Message、Handler、Looper、MessageQueue
- Android Handler、Looper、MessageQueue以及Message源码分析
- Handler、Looper、MessageQueue源码分析
- 源码浅析: Message/Handler/MessageQueue/Looper
- 源码浅析: Message/Handler/MessageQueue/Looper
- Android源码浅析: Message/Handler/MessageQueue/Looper
- Handler,Looper,MessageQueue,Message源码端理解
- Looper,Handler, HandlerThread,Message,MessageQueue分析
- Handler、Looper、Message、MessageQueue基础流程分析
- Handler、Looper、Message、MessageQueue基础流程分析
- Looper,Handler,Message,MessageQueue
- <抄>STM32 定时器有时一开启就进中断的问题
- 一天一条Linux指令-perror
- Linux下比较全面的监控工具dstat
- my bank
- From表单提交刷新页面?
- Handler,MessageQueue,Message,Looper源码分析
- nrf51822蓝牙SPI对microSD卡读写
- js--事件--通用的事件侦听器函数
- cocoapods 使用
- make menuconfig错误的解决办法
- 我的docker笔记
- 数组去重和splice() 方法split()跟join()数组方法pop() push() unshift() shift()
- The APR based Apache Tomcat Native library ...异常
- 2016年提高组模拟试题(20161105) 方程式