Android 中 Handler,Looper,HandlerThread 的关系分析
来源:互联网 发布:仆の知らない母磁力 编辑:程序博客网 时间:2024/06/08 12:15
Android 中 Handler,Looper,HandlerThread 的关系分析
最近项目中要用到 HandlerThread,对其的用法一直不甚了解,趁着五一放假就花了点时间研究一下,顺便备份在博客上。
因为刚开始研究的是 HandlerThread,所以我们就从 HandlerThread 入手,我们先来看一下它的源代码
/* * Copyright (C) 2006 The Android Open Source Project */package android.os;/** * Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called. */public class HandlerThread extends Thread { int mPriority;//线程优先级 int mTid = -1;//TID Looper mLooper;//Looper成员变量 public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT;//构造函数,设置默认线程优先级 } /** * Constructs a HandlerThread. */ public HandlerThread(String name, int priority) { super(name); mPriority = priority;//构造函数,根据参数设置线程优先级 } /** * Call back method that can be explicitly over ridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() {//主要提供给子类,让子类去重写 } public void run() {//run方法,终点来了 mTid = Process.myTid();//获取TID Looper.prepare();//后面在Looper类里看 synchronized (this) {//同步 mLooper = Looper.myLooper();//后面在Looper类里看 notifyAll();//唤醒持有该对象的并且wait的线程 } Process.setThreadPriority(mPriority);//设置线程优先级 onLooperPrepared();//HandlerThread类里没有实现,子类可以实现,做一些预处理操作 Looper.loop();//后面在Looper类里看 mTid = -1; } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) {//如果线程死掉了,返回null return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) {//如果线程活着,但是为null,就一直等待,与run方法里面的synchronized相一致 try { wait();//当线程没有被start(start之后才会alive)或者没有获取到Looper对象时wait。注意run方法中有notify操作。 } catch (InterruptedException e) { } } } return mLooper;//返回Looper成员变量 } /** * Ask the currently running looper to quit. If the thread has not * been started or has finished (that is if {@link #getLooper} returns * null), then false is returned. Otherwise the looper is asked to * quit and true is returned. */ public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit();//后面在Looper类里看 return true; } return false; } /** * Returns the identifier of this thread. See Process.myTid(). */ public int getThreadId() {//返回TID return mTid; }}
源代码不是很多,有些涉及到Looper类里面的方法,我们再来看一下Looper类的源代码(只分析涉及到的方法和成员变量)。
/* * Copyright (C) 2006 The Android Open Source Project */package android.os;import android.util.Log;import android.util.Printer;import android.util.PrefixPrinter;public 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>(); final MessageQueue mQueue; final Thread mThread; volatile boolean mRun; private Printer mLogging = null; private static Looper mMainLooper = null; // guarded by Looper.class /** 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() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper());//把和当前线程相关的Looer变量(参考Looper构造方法)放进sThreadLocal中 } /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { Looper me = myLooper();//获取和当前线程相关的Looper变量 if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } MessageQueue queue = me.mQueue;//和当前线程相关的Looper变量的MessageQueue // 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(); while (true) {//死循环哟,不过没关系,在MessageQueue中有处理,涉及到wait和notify,可以去MessageQueue中探究。 Message msg = queue.next(); // might block,获取Message if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } long wallStart = 0; long threadStart = 0; // 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); wallStart = SystemClock.currentTimeMicro(); threadStart = SystemClock.currentThreadTimeMicro(); } msg.target.dispatchMessage(msg);//这一句最关键,Message的Target是什么?没错,是Handler,下面我们就来看一下Handler类 if (logging != null) { long wallTime = SystemClock.currentTimeMicro() - wallStart; long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); if (logging instanceof Profiler) { ((Profiler) logging).profile(msg, wallStart, wallTime, threadStart, threadTime); } } // 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();//回收利用Message,所以以后我们使用Message的时候,多使用obtain方法。 } } } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); } /** * Return the {@link MessageQueue} object associated with the current * thread. This must be called from a thread running a Looper, or a * NullPointerException will be thrown. */ public static MessageQueue myQueue() { return myLooper().mQueue; } private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); } public void quit() { Message msg = Message.obtain(); // NOTE: By enqueueing directly into the message queue, the // message is left with a null target. This is how we know it is // a quit message. mQueue.enqueueMessage(msg, 0); }}
我们来看一下Handler类的源代码
/* * Copyright (C) 2006 The Android Open Source Project */package android.os;import android.util.Log;import android.util.Printer;import java.lang.reflect.Modifier;/** * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread's {@link MessageQueue}. Each Handler * instance is associated with a single thread and that thread's message * queue. When you create a new Handler, it is bound to the thread * message queue of the thread that is creating it -- from that point on, * it will deliver messages and runnables to that message queue and execute * them as they come out of the message queue. * /public class Handler { private static final boolean FIND_POTENTIAL_LEAKS = false; private static final String TAG = "Handler"; /** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. */ public interface Callback { public boolean handleMessage(Message msg); } /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { } /** * Handle system messages here. */ public void dispatchMessage(Message msg) {//重要,在Lopper.loop()方法里面里调用的就是这个方法 if (msg.callback != null) { handleCallback(msg);//msg的callBack成员变量是Runnable类型,这里执行的是msg.callback.run(),但是我们一般不给Message的callback成员变量赋值。 } else { if (mCallback != null) {//如果我们给new()的Handler类的Callback类型的成员变量赋值,就往下面执行,但是我们一般不这么做。 if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg);//我们一般在这做我们想要的操作,这个方法需要我们继承Handler类后重写。 } } /** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ 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; } /** * Constructor associates this handler with the queue for the * current thread and takes a callback interface in which you can handle * messages. */ public Handler(Callback callback) { 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; } public final Message obtainMessage() { return Message.obtain(this);//获取msg,最后调用的msg的obtain()方法,最后msg的target就是this,也就是调用者Handler } /** * Use the provided queue instead of the default one. */ public Handler(Looper looper) {//MessageQueue怎么关联起来,其实就是在这里关联起来的,通过Handler的构造方法。 mLooper = looper; mQueue = looper.mQueue; mCallback = null; } /** * Use the provided queue instead of the default one and take a callback * interface in which to handle messages. */ public Handler(Looper looper, Callback callback) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; } // 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; } private final void handleCallback(Message message) { message.callback.run(); } final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; IMessenger mMessenger;}
Looper类和Handler类的源代码不完整,只是分析了和HandlerThread相关的成员变量和方法。
经过我们的一步步分析,现在思路就清晰了:
1. 当HandlerThread运行到Looper.loop()的时候,一直死循环。通过msg.target.dispatchMessage(msg)方法让msg的target(当通过Handler的obtainMessage()系列方法获取msg的时候,msg的target就是该handler)也就是Handler去通过它的handleMessage(msg)方法去处理msg。
2. 但是msg是那里来的?通过看源代码我们发现是通过当前线程的Looper的MessageQueue类型的变量mQueue.next()方法得到的。
3. Handler也有一个MessageQueue类型的变量,那么,Handler的MessageQueue变量怎么和Looper类的MessageQueue类型变量有关系吗?
4. 记不记得Handler类有一个构造方法叫public Handler(Looper) ? 对了,就是这个构造方法让他们产生了关系。( HandlerThread有一个Looper类型的变量,通过getLooper()方法能获取,传入到Handler类的构造方法,这样,Handler就和HandlerThread联系起来了)。
5. 以至于最后HandlerThread操作的是和Handler同一个MessageQueue。
6. Handler可以通过sendMessage(msg)系列方法把msg放到MessageQueue,然后HandlerThread把msg从MessageQueue里面取出来,然后调用Handler的handleMessage(msg)方法处理。
通俗的总结一下运行时的流程:Handler把Message放到MessageQueue,HandlerThread不停的从MessageQueue里拿出来Message,然后调用Handler的HandleMessage(Message)方法不停的处理Message。
经过分析,我们来写一个demo测试一下,有消息队列的线程(非主线程):
工程如下
HandlerThread分析Demo
下面是我测试结果:
结果表示:HandlerThread确实维护了一个消息队列,从Log中可以看出他们的TID都是一样的。
总结:
1. HandlerThread维护了一个消息队列,这样我们不用到处新建对象。
2. Message其实有一套缓冲+循环利用机制,以后用到Message的地方都用obtain()系列方法获取,能节约资源,提高效率。
- Android 中 Handler,Looper,HandlerThread 的关系分析
- android Thread HandlerThread Looper Message MessageQueue Handler的关系
- android Thread HandlerThread Looper Message MessageQueue Handler的关系
- Android异步消息之Looper、Handler、Message、HandlerThread的关系
- android Thread HandlerThread Looper Message MessageQueue Handler的关系
- Android Looper,handler,HandlerThread
- Android 的Handler、Looper与HandlerThread
- Android的Looper和Handler和HandlerThread
- Handler和Looper的同步关系之HandlerThread
- Looper、Message、Handler和HandlerThread之间的关系
- Android中Handler Thread(HandlerThread) Runnable之间的关系
- Android-Handler 总结(Handler 的使用 ,Looper , MessageQueue , HandlerThread )
- Android-Handler 总结(Handler 的使用 ,Looper , MessageQueue , HandlerThread )
- Android HandlerThread、Handler、Looper、MessageQueue、Message 简单分析
- Android HandlerThread Handler Looper 三类之间的联系--学习
- Looper,Handler, HandlerThread,Message,MessageQueue分析
- android中MessageQueue,Message,Looper,handler的关系
- android 中Message、Handler、Message Queue、Looper之间的关系
- Sublime Text快捷键
- 题目1140:八皇后
- 高德V2中一些难于发现的API
- Serial Communications in Win32---MSDN
- 为什么要使用EJB?
- Android 中 Handler,Looper,HandlerThread 的关系分析
- 【项目5-扩充String类】
- 修改mysql远程账号密码
- 串的顺序存储
- 什么是REST?
- Javascript基础
- 自动化办公系统(整理中)
- select * from dictionary; oracle字典表
- linux centos 开机自启动服务