android消息处理机制
来源:互联网 发布:牛图片对比软件 编辑:程序博客网 时间:2024/06/01 09:51
Android消息处理涉及到的类有Looper,MessageQueue,Handler,Thread。下面看下它们之间的关系。
Looper
默认Thread是没有message loop的,要创建一个,在Thread的run()中执行Looper.prepare(),调用Looper.loop(),使Thread一直运行来处理消息,要让Thread停止运行,调用loop quit。
下面是示例代码
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(); } }
看看调用Looper.prepare()做了什么。
/** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ 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)); }
在prepare()中,创建了Looper实例,该实例和当前Thread关联起来,放在ThreadLocal中。
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread(); }在Looper的构造函数中创建了MessageQueue的实例。
看Looper.loop()的源码
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ 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 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); 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.recycle(); } }
queue.next()如果没有消息,会block,如果queue quit了其返回Message会是null,loop此时也会结束。拿到Message,则
msg.target.dispatchMessage(msg);
看Handler的dispatchMessage():
/** * 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); } }
如果Message没有callback,Handler的mCallback返回的是false,最终会执行handleMessage()。
当处理完一条Message后,其会被回收。
MessageQueue
MessageQueue顾名思义,用来存放Messge,Messge不是直接添加到MessageQueue,通过Handler添加的,sendMessage(),sendMessageDelayed()等方法。
通过Looper.myQueue()可以得到MessageQueue的实例。
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(); 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; }
如果没有指定Looper,会使用当前线程的Looper,如果当前线程没有looper,则报错。
public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
指定Looper。常见的使用是,先创建HandlerThread实例,并start,然后再创建Handler,使用HandlerThread实例的Looper,比如在IntentService中。
Handler的sendMessage(),sendMessageDelayed()等方法最终都会调用到sendMessageAtTime,再调用enqueueMessage
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); }
对消息处理的回调,会调用Handler的dispatchMessage()。
/** * 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); } }
Message
Message是Handler向MessageQueue发送的消息信息通过该类封装。
重要字段
int what: 用户定义的message code,消息接收者通过该code确定是哪一个消息。
int arg1,arg2:当发送的数据只是简单的1-2个int时,就用这两个变量,而不用setData(),是setData()的low-cost的替代方案。
Object obj: 发给接受者的一个任意对象。
如果要传递更多的数据,就用setData(Bundle bundle)。
获取Message实例的更好的方法是Message.obtain()
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); }
Message会从Message Pool中获取已经不再使用的Message,不需要再重新创建Message的实例。
/** * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em> * members. * @param h The <em>target</em> value to set. * @param what The <em>what</em> value to set. * @param obj The <em>object</em> 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; }或者使用Handler的obtainMessage,其也是调用Message的obtain方法。
/** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */ public final Message obtainMessage() { return Message.obtain(this); } /** * Same as {@link #obtainMessage()}, except that it also sets the what member of the returned Message. * * @param what Value to assign to the returned Message.what field. * @return A Message from the global message pool. */ public final Message obtainMessage(int what) { return Message.obtain(this, what); }
// 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;
/** * Return a Message instance to the global pool. You MUST NOT touch * the Message after calling this function -- it has effectively been * freed. */ public void recycle() { clearForRecycle(); synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
/*package*/ void clearForRecycle() { flags = 0; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; when = 0; target = null; callback = null; data = null; }
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); }
当有Message调用它的recycle()方法,比如在Looper.loop()中,clearForRecycle()将所有变量置空,sPool将值赋给当前Message对象的next,当前Message对象赋值给sPool,当下一个Message对象m2调用recycle时,m2的next指向之前sPool的值,即上一个Message对象,将m2赋值给sPool。
调用obtain时,如果sPool不为空,则有回收的Message,返回该Message,将该Message的next,即之前的Message赋值给sPool。
Message的类变量sPool,总是指向回收的Message链表的头元素,它相当于一个头指针。
总结
- 在Thread的run()中调用Looper.prepare()给Thread创建looper,调用Looper.loop()使Thread监听MessageQueue,准备处理消息;
- 创建Handler时默认的Looper是当前线程的Looper,也可以指定Looper,sendMessage()即向Looper所持有的MessageQueue发送消息,Thread从MessageQueue取得Handler发来的消息后,回调Handler的callBack或者handleMessage();
- 当处理完一条Message,调用Message的recycle(),放到Message Pool中备用;
- 当调用Looper的quit,会调用到MessageQueue的quit(),之后Thread的run方法执行完毕。
- Android 消息处理机制
- Android消息处理机制
- Android消息处理机制
- android消息处理机制
- android 消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- android消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- Android消息处理机制
- 有关注册表中涉及到的鼠标右键项目
- Scala入门到精通——第二十三节 高级类型 (二)
- Qt5+VS2013 “LINK : fatal error LNK1117: 选项“VERSION:1.0.0”中的语法错误”
- SGM是什么?
- oracle查看awr、addm报告
- android消息处理机制
- Dijkstra
- 利用系统ContentProvider增加联系人
- iOS学习笔记:UISearchBar使用
- JS正则表达式详解
- 最小二乘回归
- fcntl的close-on-exec标志
- easyUI设置textbox的值
- Commons lang3 包ArrayUtils类使用