android Looper HandlerThread MessageQueue Handler Message(完善中......)
ActivityThread.java 的 main主函数启动入口
从prepareMainLooper方法的注释可以理解,初始化当期线程,而looper和一个线程关联,并且提供了主线程looper对象的对外接口
/** Initialize the current thread as a looper, marking it as an application's main * looper. The main looper for your application is created by the Android environment, * so you should never need to call this function yourself. * {@link #prepare()} */ public static final void prepareMainLooper() { prepare(); setMainLooper(myLooper()); if (Process.supportsProcesses()) { myLooper().mQueue.mQuitAllowed = false; } } private synchronized static void setMainLooper(Looper looper) { mMainLooper = looper; } /** Returns the application's main looper, which lives in the main thread of the application. */ public synchronized static final Looper getMainLooper() { return mMainLooper; } 初始化当前线程,之后把一个初始化的Looper关联线程,在Looper初始化的时候做了一些操作就是初始化了一个消息队列MessageQueue即通过Looper来管理MessageQueue,通过调用Looper.myLooper()可以获得当前线程的Looper对象,但是Looper的构造函数是私有的,外界无法直接实例化之;要实例化,只有通过Looper::prepare() // sThreadLocal.get() will return null unless you've called prepare(). private static final ThreadLocal sThreadLocal = new ThreadLocal(); /** 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 final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static final Looper myLooper() { return (Looper)sThreadLocal.get(); }looper里面的消息队列进行循环机制,执行消息队列里面的一个个消息,注意msg.target是个Handler对象
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block //if (!me.mRun) { // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } }
轮循中开始处理系统的一个个消息,两种情况一种正常消息处理,一种回掉处理;其中
handleMessage(msg)为需要用户自己继承Handler来覆盖此方法作为用户需要执行的任务。
理解下HandlerThread,你会发现HandlerThread继承Thread,HandlerThread::run()里面调用了Looper的初始化prepare();和looper()。
理解Handler,从下面的Handler构造函数可以了解Handler的构造是需要Looper对象的,没有参数Looper的构造函数是用当前线程的looper对象;而当然你也可以通过HandlerThread施行run后就有了looper对象,通过对外的接口getLooper()可以获取此Looper对象,MessageQueue在looper中是一个属性,所以你需要记忆这个。
public Handler() { 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 = null; } /** * Use the provided queue instead of the default one. */ public Handler(Looper looper) { mLooper = looper; mQueue = looper.mQueue; mCallback = null; }说明:对于以上的理解我在最后会有实例来验证说明,到这里我们的疑问是现在我们想知道 消息是怎么封装的,消息是怎么放入消息队列的?
消息的入消息队列
/** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /** * Enqueue a message into the message queue after all pending messages * before (current time + delayMillis). You will receive it in * {@link #handleMessage}, in the thread attached to this handler. * / public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } /** * Enqueue a message into the message queue after all pending messages * before the absolute time (in milliseconds) <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * You will receive it in {@link #handleMessage}, in the thread attached * to this handler. * / public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } final boolean enqueueMessage(Message msg, long when) { if (msg.when != 0) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; //Log.d("MessageQueue", "Enqueing: " + msg); Message p = mMessages; if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; this.notify(); } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; this.notify(); } } return true; }通过上面的理解,用实例来验证上面的理解,下面是我以前项目中写的代码。
实例一:在一个activity耗时的操作方法中自己起了一个线程
Thread th = new Thread() { public void run() { Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { public void run() { Toast.makeText(MailView.this, "�ʼ����ͳɹ�", Toast.LENGTH_LONG).show(); } } ) } } th.start();实例二:Service中,这里注意下,Message的对象创建Message::obtain(),这个对象也可以是Handler的obtainMessage()来创建。
private final Handler handler = new Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case MSG_TIMER: mWorker = new HandlerThread("MyWorker"); mWorker.start(); mWorkerHandler = new Handler(mWorker.getLooper()); mWorkerHandler.postDelayed(new MessageReceiveTask(), SECONDRESOLVERMESSAGE); break; } } }; public void onCreate() { super.onCreate(); Log.i(Constant.TAG_INFO, "StartService*****************************************"); Message msgget = Message.obtain(); msgget.what = MSG_TIMER; handler.sendMessageDelayed(msgget, SECONDRESOLVERMESSAGELONG); } class MessageReceiveTask implements Runnable {
public void run() {
try {
loadInitInboxData();
} catch (Exception e) {
Log.i(Constant.TAG_EXCEPTION, "MessageReceiveTask : " + e);
}
mWorkerHandler.postDelayed(this, SECONDRESOLVERMESSAGE);
}
}
从上面我写的代码可以看到发送有两种方式,sendMessage(m)和postDelayed(r)两种,我列出源码
/** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } /** * Causes the Runnable r to be added to the message queue, to be run * after the specified amount of time elapses. * The runnable will be run on the thread to which this handler * is attached. * */ public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } /** * Causes the Runnable r to be added to the message queue, to be run * at a specific time given by <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * The runnable will be run on the thread to which this handler is attached. * @see android.os.SystemClock#uptimeMillis */ public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } /** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. */ public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /** * Enqueue a message into the message queue after all pending messages * before (current time + delayMillis). You will receive it in * {@link #handleMessage}, in the thread attached to this handler. */ public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } /** * Enqueue a message into the message queue after all pending messages * before the absolute time (in milliseconds) <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * You will receive it in {@link #handleMessage}, in the thread attached * to this handler. */ public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } 下班了,。。。。。。上面是一个流程的了解,下面我们需要对细节的了解,这个有待继续。下面是message的创建,请注意这里,先从池中取出,需要明白下面是个单向链表的形式,从注释中可以了解到:// sometimes we store linked lists of these things
Message next;如果在池中没有就从新new一个对象。
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (mPoolSync) { if (mPool != null) { Message m = mPool; mPool = m.next; m.next = null; return m; } } return new Message(); }
注意message要是用完后,需要回收放入池中
/** * 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() { synchronized (mPoolSync) { if (mPoolSize < MAX_POOL_SIZE) { clearForRecycle(); next = mPool; mPool = this; } } }
从// might block这个注释说开来,
public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block 取消息队列中的消息,如果没有就有可能堵塞 //if (!me.mRun) { // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } } 继续说明消息是怎么取的final Message next() { boolean tryIdle = true; while (true) { long now; Object[] idlers = null; // Try to retrieve the next message, returning if found. synchronized (this) { now = SystemClock.uptimeMillis(); Message msg = pullNextLocked(now); 具体的通过单向链表方式来操作的,看这个方法的具体内容就明白了。 if (msg != null) return msg; if (tryIdle && mIdleHandlers.size() > 0) { idlers = mIdleHandlers.toArray(); } } // There was no message so we are going to wait... but first, // if there are any idle handlers let them know. boolean didIdle = false;//no idle if (idlers != null) { for (Object idler : idlers) { boolean keep = false; try { didIdle = true; keep = ((IdleHandler)idler).queueIdle(); } catch (Throwable t) { Log.e("MessageQueue", "IdleHandler threw exception", t); RuntimeInit.crash("MessageQueue", t); } if (!keep) { synchronized (this) { mIdleHandlers.remove(idler); } } } } // While calling an idle handler, a new message could have been // delivered... so go back and look again for a pending message. if (didIdle) { tryIdle = false; continue; } synchronized (this) { // No messages, nobody to tell about it... time to wait! try { if (mMessages != null) { if (mMessages.when-now > 0) { Binder.flushPendingCommands(); this.wait(mMessages.when-now); 这里需要说明的是堵塞等待一个特定的时间 } } else { Binder.flushPendingCommands(); this.wait(); 堵塞 ,期待唤醒 } } catch (InterruptedException e) { } } } } 下面是通过比较当前系统的真实时间long来和消息的message的when时间值来比较,如果当前时间大于或等于消息时间,就把当前节点取出来,把下一个赋值给当前节点。
final Message pullNextLocked(long now) {
Message msg = mMessages;
if (msg != null) {
if (now >= msg.when) {
mMessages = msg.next;
if (Config.LOGV) Log.v(
"MessageQueue", "Returning message: " + msg);
return msg;
}
}
return null;
}
消息的入对列也是单向列表式的操作
final boolean enqueueMessage(Message msg, long when) { if (msg.when != 0) { throw new AndroidRuntimeException(msg + " This message is already in use."); } 上面的msg.when!=0是因为之前这个方法被调用前没有被赋值过,如果被赋值过,则说明已经被使用中了。 if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; //Log.d("MessageQueue", "Enqueing: " + msg); Message p = mMessages; if (p == null || when == 0 || when < p.when) { msg.next = p; 把当前的节点赋值给传进来的message的下一个,而下面一句则是把传进来的message作为最新的当前节点。 mMessages = msg; 下面一句是唤醒,通过上面的判断有消息入队,则进行唤醒来进行处理。 this.notify(); } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; this.notify(); } } return true; }
现在你开朗了吗?。。。。。。
推荐阅读
-
Android Handler 机制 - Looper,Message,MessageQueue
-
Android消息处理机制(Handler、Looper、MessageQueue与Message)
-
Android消息机制总结 Handler Looper MessageQueue Message
-
android中MessageQueue , Message , Looper , Handler(三)
-
Android中的Handler、Looper、Message、MessageQueue之间流程关系
-
android中message、messageQueue、Handler、looper的关系
-
Android 异步消息机制(Looper、Handler、MessageQueue、Message关系)
-
Android系统中Thread,Looper,MessageQueue,Message,Handler相互关系的简单分析
-
android Looper HandlerThread MessageQueue Handler Message(完善中......)
-
Android中的消息系统————Handler,MessageQueue与Looper