Android消息机制之Handler,MessageQueue,Looper源码剖析

上传人:痛*** 文档编号:83023192 上传时间:2022-04-30 格式:DOC 页数:55 大小:188KB
返回 下载 相关 举报
Android消息机制之Handler,MessageQueue,Looper源码剖析_第1页
第1页 / 共55页
Android消息机制之Handler,MessageQueue,Looper源码剖析_第2页
第2页 / 共55页
Android消息机制之Handler,MessageQueue,Looper源码剖析_第3页
第3页 / 共55页
点击查看更多>>
资源描述
wordAndroid消息机制之Handler,MessageQueue,Looper源码剖析Android线程间通讯方式有很多,但是大局部内部实现其实都是handler。今天我们就来看看handler的内部实现机制,实现原理,实现细节。本文主要是为了搞清楚线程间的通讯,Message也可以用于进程间的通讯,在本文中不对此进展详细的讲解,浅尝辄止!后面如果有需要,我会补上Message的进程间通讯相关文章,敬请期待! 本位我们分步骤对Handler消息机制进展分析,这样有条理一点,已更利于阅读。角色分析:Handler进程间通讯主要关联了Thread,ThreadLocal,Handler,Message,MessageQueue,Looper,,这几个类在内。我们先看看这几个类各自在这个实现工程中扮演者什么样的角色!Thread:整个机制产生的意义,所有这个机制就是为Thread服务!Looper的创建是为Thread而创建,其实是Thread持有。Handler使用的Looper是由Thread提供!ThreadLocal:Thread属性的存储者,内部维护一个ThreadLocalMap,其中存放了Thread的所有属性,Looper就是存放在这儿。Handler:消息的发起者,发出一个消息。消息的处理者,消息处理的时间到了对该消息进展处理。必须有一个Looper,通过操作Looper持有的MessageQueue实现消息的发送,当Looper通知处理Message的时候,对Message进展处理。Message:数据和信号携带者,携带数据进展传递。处理时机决定者,通过when属性决定消息的处理时间。消息队列的产生者,将一个个的message对象串联起来,形成消息队列。MessageQueue:消息存放者,存放了一个消息队列,有消息进来的时候安插在指定的位置,需要处理的时候将消息取出来。消息排队者,将消息按处理的时间进展存放,让消息排队进展处理。Looper:运行机制全局掌控者,让整个机制活动起来的关键人员,将所有角色联系起来,根据具体实现进展调度,完成整个机制的任务。内部持有一个MessageQueue,Handler通过关联Looper,联系上MessageQueue。大体的运转结构了解了这些类在整个任务中充当的角色何彼此之间的联系之后,我们来看看他们大体都做了些什么工作,让整个机制运转起来。Handler通过sendMessage方法,将Message发送出去,MessageQueue通过queueMessage方法将消息存插入到消息队列中等待被处理。Looper通过loop方法在特定的时间到MessageQueue中将消息取出来,回调Handler的dispatchMessage方法将消息交给Handler处理。具体为什么就将数据在线程之间传递成功了呢?通过第2点,我们大体了解了整个机制的原理,但是这样做为什么就能实现线程间数据的传递呢?这个问题很关键,在我们源代码分析完了之后再来进展讲解,这儿先不说。源代码剖析:下面我们对源代码进展剖析,然后再来看看上面提到的理论和问题,整个消息机制就完全理解掌握了!Handler源码分析:public class Handler private static final boolean FIND_POTENTIAL_LEAKS = false; private static final String TAG = Handler; /当前handler所在线程的looper final Looper mLooper; /跟looper对应的消息队列 final MessageQueue mQueue; /处理消息的回调 final Callback mCallback; /决定处理消息的方式同步的还是异步的 final boolean mAsynchronous; IMessenger mMessenger; /* * 通过设置这个接口去处理消息,就不需要再定义一个Handler的子类 */ public interface Callback public boolean handleMessage(Message msg); /* * Subclasses must implement this to receive messages. * Message和Handler都没有callback才会调用处理消息,这儿啥也没做,留着口给子类去完成了 */ public void handleMessage(Message msg) /* * 处理系统消息 * Handle system messages here. */ public void dispatchMessage(Message msg) /如果msg有回调就交给msg处理 if (msg.callback != null) handleCallback(msg); else /msg没有回调,创建Handler的时候有给回调就交给这个回调处理 if (mCallback != null) if (mCallback.handleMessage(msg) return; /调用自己的handleMessage方法处理,什么也没做,交给子类去具体实现,具体操作。平时我们用的匿名内部类的方式就是走了这一步 handleMessage(msg); public Handler() this(null, false); /* * 构造方法,设定消息处理回调,如果当前线程中没有Looper的时候,将接不到消息,还会抛出异常 */ public Handler(Callback callback) this(callback, false); /* * 构造方法,指定一个Looper,用这个Looper替换默认的Looper */ public Handler(Looper looper) this(looper, null, false); public Handler(Looper looper, Callback callback) this(looper, callback, false); /* * 设定当前Handler是同步处理消息还是异步处理消息 */ public Handler(boolean async) this(null, async); /* * 构造方法,初始化 */ public Handler(Callback callback, boolean async) if (FIND_POTENTIAL_LEAKS) final Class 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(); /获取一个Looper,UI线程系统自动调用prepareMainLooper方法,创建了UI线程的looper /如果Handler在子线程中创建,必须先调用prepare创建一个looper,否如此myLooper返回的是null,会抛出异常 mLooper = Looper.myLooper(); if (mLooper = null) throw new RuntimeException( Cant create handler inside thread that has not called Looper.prepare(); / mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; /* * 构造方法,初始化。跟2个参数的构造方法的区别是,这儿直接给定了looper */ public Handler(Looper looper, Callback callback, boolean async) mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; /* * 获取trace文件的名字,ANR分析的时候有用 */ public String getTraceName(Message message) final StringBuilder sb = new StringBuilder(); sb.append(getClass().getName().append(: ); if (message.callback != null) sb.append(message.callback.getClass().getName(); else sb.append(#).append(message.what); return sb.toString(); /* * 获取消息的名称,用消息的callback类名或者what的十六进制命名 * * param message The message whose name is being queried */ public String getMessageName(Message message) if (message.callback != null) /如果规定了message的回调,返回该回调类的名字 return message.callback.getClass().getName(); /如果message没有指定回调,返回what的十六进制 return 0x + Integer.toHexString(message.what); /* * 从消息池中获取一个回收的message对象返回, * 但是这个message的处理handler是调用该方法的handler * 这样效率比直接new一个Message要好 */ public final Message obtainMessage() return Message.obtain(this); /* * 跟上面的方法差不多,只是多了一点,指定了message的what变量值 */ public final Message obtainMessage(int what) return Message.obtain(this, what); public final Message obtainMessage(int what, Object obj) return Message.obtain(this, what, obj); public final Message obtainMessage(int what, int arg1, int arg2) return Message.obtain(this, what, arg1, arg2); public final Message obtainMessage(int what, int arg1, int arg2, Object obj) return Message.obtain(this, what, arg1, arg2, obj); /* * 将一个Runnable放到消息队列中,处理的时候是由当前handler依附的线程处理 */ public final boolean post(Runnable r) return sendMessageDelayed(getPostMessage(r), 0); /* * 跟上面的方法一样,只是多了一个执行的时间指定,会在(uptimeMillis)这段时间过后才执行 */ public final boolean postAtTime(Runnable r, long uptimeMillis) return sendMessageAtTime(getPostMessage(r), uptimeMillis); public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); public final boolean postDelayed(Runnable r, long delayMillis) return sendMessageDelayed(getPostMessage(r), delayMillis); public final boolean postAtFrontOfQueue(Runnable r) return sendMessageAtFrontOfQueue(getPostMessage(r); public final boolean runWithScissors(final Runnable r, long timeout) if (r = null) throw new IllegalArgumentException(runnable must not be null); if (timeout 0) throw new IllegalArgumentException(timeout must be non-negative); if (Looper.myLooper() = mLooper) r.run(); return true; BlockingRunnable br = new BlockingRunnable(r); return br.postAndWait(this, timeout); /* * 移除消息队列中所有待处理的任务 */ public final void removeCallbacks(Runnable r) mQueue.removeMessages(this, r, null); /* * Remove any pending posts of Runnable r with Object * token that are in the message queue. If token is null, * all callbacks will be removed. */ public final void removeCallbacks(Runnable r, Object token) mQueue.removeMessages(this, r, token); /* * 将消息push到消息队列的队尾,轮到处理该消息的时候会回调handleMessage去处理 * 如果push成功返回true,如果这个消息队列已经exiting,将会push失败,返回false */ public final boolean sendMessage(Message msg) return sendMessageDelayed(msg, 0); /* * 将一个没有携带数据,只有what值的空消息push到消息队列中 */ public final boolean sendEmptyMessage(int what) return sendEmptyMessageDelayed(what, 0); /* * 将一个没有携带数据,只有what值的空消息push到消息队列中,但是会在特定的时间过后才能被delivered */ public final boolean sendEmptyMessageDelayed(int what, long delayMillis) Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); /* * 将一个消息放入队列,在当前时间+delayMillis(比如:一个小时之后处理,现在是12点,那就是12:00+1*60*60*1000) * 时间点之前应该要处理的消息全部处理完了之后,会在当前handler依附的线程中处理该消息。 * 这个消息将被传到handleMessage方法中 */ public final boolean sendMessageDelayed(Message msg, long delayMillis) if (delayMillis 0) delayMillis = 0; return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); /* * 将一个消息放入消息队列,在uptimeMillis(比如13:00)这个绝对时间点之前应该处理的消息处理完成之后会处理该消息 */ 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); /* * 讲一个消息放在队首,这个方法一般不会使用,需要在特定的情况下使用。因为这个方法可能会导致 * 消息队列的排序出现问题,或者一些无法想象的异常出现 */ public final boolean sendMessageAtFrontOfQueue(Message msg) 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, 0); /* * 将消息放入队列中,在uptimeMillis13:00处理这个消息 * * param queue 将消息放入这个消息队列 * param msg 想要处理的消息 * param uptimeMillis 处理的绝对时间点 * return */ private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) /指定处理该消息的handler为当前调用的handler msg.target = this; if (mAsynchronous) /将消息设置为可异步 msg.setAsynchronous(true); return queue.enqueueMessage(msg, uptimeMillis); /* * 从消息队列中移除指定what值的,未处理的消息.移除之后这些消息对象会被回收,将不会被取出执行 */ public final void removeMessages(int what) mQueue.removeMessages(this, what, null); /* * 从消息队列中移除指定what,和obj值,并且未处理的消息,移除之后这些消息对象会被回收,将不会被取出执行 */ public final void removeMessages(int what, Object object) mQueue.removeMessages(this, what, object); /* * 从消息队列中移除所有指定obj值,并且未处理的消息和任务,移除之后这些消息对象会被回收,将不会被取出执行 */ public final void removeCallbacksAndMessages(Object token) mQueue.removeCallbacksAndMessages(this, token); /* * 查询消息队列中是否有跟指定what值的消息 */ public final boolean hasMessages(int what) return mQueue.hasMessages(this, what, null); /* * Check if there are any pending posts of messages with code what and * whose obj is object in the message queue. */ public final boolean hasMessages(int what, Object object) return mQueue.hasMessages(this, what, object); /* * 查询消息队列中是否有指定任务 */ public final boolean hasCallbacks(Runnable r) return mQueue.hasMessages(this, r, null); / if we can get rid of this method, the handler need not remember its loop / we could instead export a getMessageQueue() method. public final Looper getLooper() return mLooper; public final void dump(Printer pw, String prefix) pw.println(prefix + this + + SystemClock.uptimeMillis(); if (mLooper = null) pw.println(prefix + looper uninitialized); else mLooper.dump(pw, prefix + ); Override public String toString() return Handler ( + getClass().getName() + ) + Integer.toHexString(System.identityHashCode(this) + ; .Message源码分析:public final class Message implements Parcelable /* * 用于指定当前消息的身份 */ public int what; /* * 该消息所携带的简单数据 */ public int arg1; /* * 消息所携带的简单数据 */ public int arg2; /* * 一个Object类型的数据,这个数据可以用于进程间数据传递,这儿不深究 */ public Object obj; /* * Optional Messenger where replies to this message can be sent. The * semantics of exactly how this is used are up to the sender and * receiver. */ public Messenger replyTo; /* * 通过 link Messenger进展进程间数据传递的时候才会有效,代表发送消息的进程的UID,一般情况下为-1,这儿同样不进展深究; */ public int sendingUid = -1; /* * 用于标志当前消息是否正在使用 */ /*package*/ static final int FLAG_IN_USE = 1 0; /* * 用于标志当前消息的同步和异步 */ /*package*/ static final int FLAG_ASYNCHRONOUS = 1 1; /* * Flags to clear in the copyFrom method */ /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE; /*package*/ int flags; /*package*/ long when; /*package*/ Bundle data; /* * 处理该消息的handler */ /*package*/ Handler target; /* * 处理消息的回调,如果没有这个回调将会调用Handler的handleMessage方法进展处理 */ /*package*/ Runnable callback; /* * 保存了下一个message对象的地址 */ /*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; private static boolean gCheckRecycle = true; /* * 从消息池中获取一个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(); /* * 从消息池中获取一个message对象返回,防止过多创建对象 * 并且将传进来的消息中的数据复制给message,并返回 */ public static Message obtain(Message orig) Message m = obtain(); m.what = orig.what; m.arg1 = orig.arg1; m.arg2 = orig.arg2; m.obj = orig.obj; m.replyTo = orig.replyTo; m.sendingUid = orig.sendingUid; if (orig.data != null) m.data = new Bundle(orig.data); m.target = orig.target; m.callback = orig.callback; return m; /* * 从消息池中获取一个message对象返回,防止过多创建对象 * 指定一个handler去处理 */ public static Message obtain(Handler h) Message m = obtain(); m.target = h; return m; /* * 从消息池中获取一个message对象返回,防止过多创建对象 * 指定一个handler去处理 * 并指定处理的回调接口 */ public static Message obtain(Handler h, Runnable callback) Message m = obtain(); m.target = h; m.callback = callback; return m; /* * Same as link #obtain(), but sets the values for both target and * what members on the Message. * * param h Value to assign to the target member. * param what Value to assign to the what member. * return A Message object from the global pool. */ public static Message obtain(Handler h, int what) Message m = obtain(); m.target = h; m.what = what; return m; /* * Same as link #obtain(), but sets the values of the target, what, and obj * members. * * param h The target value to set. * param what The what value to set. * param obj The object method to set. * return A Message object from the global pool. */ public static Message obtain(Handler h, int what, Object obj) Message m = obtain(); m.target = h; m.what = what; m.obj = obj; return m; /* * Same as link #obtain(), but sets the values of the target, what, * arg1, and arg2 members. * * param h The target value to set. * param what The what value to set. * param arg1 The arg1 value to set. * param arg2 The arg2 value to set. * return A Message object from the global pool. */ public static Message obtain(Handler h, int what, int arg1, int arg2) Message m = obtain(); m.target = h; m.what = what; m.arg1 = arg1; m.arg2 = arg2; return m; /* * Same as link #obtain(), but sets the values of the target, what, * arg1, arg2, and obj members. * * param h The target value to set. * param what The what value to set. * param arg1 The arg1 value to set. * param arg2 The arg2 value to set. * param obj The obj value to set. * return A Message object from the global pool. */ public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) Message m = obtain(); m.target = h; m.what = what; m.arg1 = arg1; m.arg2 = arg2; m.obj = obj; return m; /* * hide */ public static void updateCheckRecycle(int targetSdkVersion) if (targetSdkVersion Build.VERSION_CODES.LOLLIPOP) gCheckRecycle = false; /* * 回收message,先检查当前消息是否正在使用,如果正在使用抛出异常 * 如果没有使用就会回收掉,回收之后将不能再使用这个消息 */ public void recycle() if (isInUse() if (gCheckRecycle) throw new IllegalStateException(This message cannot be recycled because it + is still in use.); return; recycleUnchecked(); /* * 内部调用回收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+; /* * 复制o的数据不包括队列相关的数据给当前消息 */ public void copyFrom
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!