Android异步消息处理机制的源码分析

###1、背景###
相信做过一段时间的Android开发都了解,当我们在子线程中更新UI时会抛出异常,导致程序崩溃,Android4.0之后只允许在UI线程中更新界面,但是我们也不能再UI线程中处理耗时操作,那样会导致应用程序无响应(即出现ANR)。
那如果想解决以上问题我们应该如何操作呢?我相信大家肯定都会想到使用Android的异步机制,没错这也是最简单的一种处理方式。异步机制的使用我相信大家都已经很熟悉了,那今天我们就从源码的角度来分析一下该机制。

###2、 示例 ###
首先我们来看一个简单的Handler应用示例代码

public class HandlerTestActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initData();
	}

	private void initData() {
		new Thread() {
			public void run() {
				// (1)这步很重要
				Looper.prepare();

				new Handler() {
					public void handleMessage(Message msg) {
						// 代码逻辑处理
						mHandler.sendEmptyMessage(0);
					};
				};
				// (2)这步也很重要
				Looper.loop();
			};
		}.start();
	}

	// (3)这里有一个内存泄漏问题
	// This Handler class should be static or leaks might occur
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 0:
				// 接收消息后的处理
				break;
			default:
				break;
			}
		};
	};

	protected void onStop() {
		super.onStop();
		mHandler.removeCallbacksAndMessages(null);
	};
}

以上就是最简单的Handler在子线程中操作UI线程,对于Handler的使用大家可以自己去摸索,我们今天的重点在于对Handler的源码进行分析。

###3、源码分析###
本次分析的源码是基于Android5.1系统,我们首先从Handler的构造函数开始入手吧。

Handler和Looper实例化

Handler有多个重载的构造器,但是都是大同小异的,所以我们就分析一个使用最多的无参构造器。

/**
  * Default constructor associates this handler with the {@link Looper} for the
  * current thread.
  * If this thread does not have a looper, this handler won't be able to receive messages so an exception is thrown.
  */
    public Handler() {
        this(null, false);
    }

这是Handler最常使用的无参构造器,它调用了本类另外一个有参构造器。
PS:注释也很重要,如果当前线程没有looper,这个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());
            }
        }
//(1)这里获取一个Looper对象
        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;
    }

我们进入到Handler的另外一个构造器中,代码中的(1)处mLooper = Looper.myLooper(),这里获取Looper对象,如果获取的Looper对象为null,将抛出Can’t create handler inside thread that has not called Looper.prepare()异常。

我们进入到Looper对象的myLooper方法中

/**
  * 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();
    }

这里只是简单的从sThreadLocal中通过get方法获取Looper对象,我们来看一下sThreadLocal是什么?

// sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

它是一个static final类型的ThreadLocal <Looper>对象,所以当sThreadLocal中存在Looper对象时将取出Looper对象,否则将返回null。

既然可以通过sThreadLocal对象取出Looper对象,那一定会有set()方法将Looper存入sThreadLocal对象中,是的接下来我们看一下哪里有set方法。

还记得之前在子线程中调用Handler的方法之前需要调用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");
        }
        //(1)我们重点看此处代码
        sThreadLocal.set(new Looper(quitAllowed));
    }

由源码可见prepare方法直接调用的是prepare(boolean)方法,这里是对prepare方法做了一次封装,参数quitAllowed直接传入true(Ps:这个参数很重要,涉及到能否退出消息队列),我们看(1)处代码sThreadLocal.set(new Looper(quitAllowed)),终于看到了sThreadLocal对象的set方法啦,它设置的是一个Looper对象,进入该方法。

private Looper(boolean quitAllowed) {
   mQueue = new MessageQueue(quitAllowed);
   mThread = Thread.currentThread();
}

可以看到Looper的构造函数中创建了一个MessageQueue对象(Ps:MessageQueue是一个消息队列,用于将收到的消息进行排列,并按序处理),并获取到当前线程,这里可以看出一个Looper对象只有一个MessageQueue。

这里就有一个疑问了,那我们平时在UI线程中创建Handler时并没有调用Looper.prepare()方法,但在使用的过程中也没有抛出异常啊?这是因为在UI线程(Activity等)启动时已经帮我们调用了Looper.prepare()方法了,我们来看其源码。但在看其源码之前我们先说明一下,我们平时一直都认为Activity的入口是OnCreate方法,其实Android应用的上一个入口是ActivityThread类的main方法,这个我们将在后面的博客中详述。
我们进入ActivityThread.java类的main方法

public static void main(String[] args) {
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        Security.addProvider(new AndroidKeyStoreProvider());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");
		//(1)此处调用了Looper.prepareMainLooper()方法
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
		//(2)此处调用了Looper.loop()方法
        Looper.loop();
		//(3)此处抛出一个异常
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

1、我们先看(1)处代码,此处调用了Looper.prepareMainLooper()方法, 我们进入该方法。

/**
 - 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.  See also: {@link #prepare()}
  */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    /** Returns the application's main looper, which lives in the main thread of the application.
     */
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

通过prepareMainLooper方法可以看出,该方法通过调用myLooper()方法从而得到一个Looper对象,这个Looper对象一直保存在sMainLooper变量中,当需要获取该对象时只需调用getMainLooper()方法即可。
2、我们再来看(2)(3)两处代码,(2)处和之前一样调用了loop()方法,而(3)处此时却抛出异常,其实在这里完全不用担心抛出异常会有问题,因为(2)这里是一个死循环,正常情况下程序无法到达(3)处,除非程序出现异常,好啦我们对Handler的构造器和Looper.prepare()方法也就分析到这里了,我们来总结一下。

  • 当我们在主线程中可以直接创建Handler,而在子线程中需要先调用Looper.prepare()后才能创建Handler,否在会抛出Can’t create handler inside thread that has not called Looper.prepare()的异常。
  • 可通过Looper.myLooper()方法获取当前线程的Looper对象,而通过Looper.getMainLooper()方法获取主线程Looper实例。
  • 每个线程只能拥有一个Looper对象,否则会抛出异常,而一个Looper也只能对应一个MessageQueue。
  • 一个线程只能有一个Looper实例,一个MessageQueue实例,可以有多个Handler实例。

到这里Handler我们也创建好了,也就可以开始分析发送和处理消息的源码了。

Handler收发消息机制

Handler有多个重载的发送消息的方法,如sendMessage,sendEmptyMessageDelayed,sendEmptyMessage等,但是通过源码发现除了sendMessageAtFrontOfQueue方法外,其余的发送消息的方法最终都会通过sendMessageAtTime方法来发送消息,现在我们来看一下这两个方法的区别。
咱们先看sendMessageAtTime方法:

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
		//(1)注意这里的赋值语句,此处的mQueue是Handler中的变量
        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);
    }

紧接着我们在来看一下sendMessageAtFrontOfQueue方法:

public final boolean sendMessageAtFrontOfQueue(Message msg) {
//(1)注意这里的赋值语句,此处的mQueue是Handler中的变量
        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);
    }

通过源码可以发现,表面上sendMessageAtFrontOfQueue和其他发送消息的方法不同,但实质上是相同的,sendMessageAtFrontOfQueue方法其实就是sendMessageAtTime方法的一个特例(即传入的uptimeMillis=0,也就是可以通过这个方法将message放入Queue的最前面),同时注意(1)处代码,将Handler的变量mQueue赋值给局部变量queue。

那这样我们就可以直接分析sendMessageAtTime方法,可以看到其最终调用了enqueueMessage这个方法,我们进入该方法:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
		//(1)注意此处的代码逻辑,将Handler本身赋值给msg.target变量(重要)
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

发现该方法有三个参数:

  • queue参数:是上一个方法的sendMessageAtTime传递而来的,而最终Handler的mQueue变量是在哪里赋值的呢?其实之前我们分析过,在Handler的构造器中有mQueue = mLooper.mQueue,此时将Looper的变量mQueue赋值过来,而Looper的mQueue变量是在Looper的构造器中创建出来的
  • msg参数:即我们需要发送的消息
  • uptimeMillis参数:表示发送消息的时间

同时请注意(1)处代码逻辑,将需要发送的消息msg的target属性赋值为Handler对象(也就是进行绑定),紧接着调用了queue对象的enqueueMessage方法,我们进入该方法。

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("MessageQueue", 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;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

通过这段代码发现Handler发送消息的实质就是将Message加入到MessageQueue的过程,另可以看出消息插入队列的实质就是将所有的消息按时间进行排序(uptimeMillis参数)。

到这里Handler如何发送消息以及将消息如何存入队列就分析结束了,那既然消息都已经存入队列了,现在我们也该学习如何从队列中取出消息了。还记得之前的示例中我们在子线程中调用了Looper.loop()方法吗?其实该方法就是从队列中取出消息,我们来看其源码。

/**
  * Run the message queue in this thread. Be sure to call
  * {@link #quit()} to end the loop.
  */
    public static void loop() {
	    //(1)通过Looper的myLooper静态方法获得Looper对象
        final Looper me = myLooper();
        //如果在调用loop方法之前没有调用prepare方法将会抛出异常
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //(2)此处通过Looper对象mQueue属性获得消息队列
        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();
		//(3)此处为死循环,然后通过MessageQueue的next方法不断的获取消息
        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);
            }
			//(4)此处调用msg.target对象的dispatchMessage()方法
            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.recycleUnchecked();
        }
    }

我们来分析上面源码中的(1)-(4)处逻辑。
(1):此处通过Looper的myLooper方法获得Looper对象
(2):此处通过Looper对象mQueue属性获得消息队列
(3):此处通过死循环不断的获得消息队列的中的消息,当消息队列中没有消息时,该方法将会进入阻塞状态,并一直等待新消息
(4):此处调用msg.target对象的dispatchMessage()方法,还记得之前我们将什么对象赋值给msg.target属性吗?在Handler的enqueueMessage方法中,我们将msg.target = this即Handler对象赋值给msg.target属性,所以此处自然的回调了Handler的dispatchMessage()方法。

接下来我们的重点将进入Handler的dispatchMessage方法。

/**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
	    //(1)这里是第一种处理方式
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
	        //(2)这里是第二种处理方式
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            //(3)这里是第三种处理方式
            handleMessage(msg);
        }
    }

在dispatchMessage方法中有三种方式处理msg消息,我们分别看一下这三种方式处理的函数。

//(1)
	private static void handleCallback(Message message) {
        message.callback.run();
	}
//(2)
/**
  * Callback interface you can use when instantiating a Handler to avoid
  * having to implement your own subclass of Handler.
  *
  * @param msg A {@link android.os.Message Message} object
  * @return True if no further handling is desired
  */
	 public interface Callback {
        public boolean handleMessage(Message msg);
    }
//(3)
/**
  * Subclasses must implement this to receive messages.
  */
	 public void handleMessage(Message msg) {
    }

以上分别为dispatchMessage中对应的三种处理方式,我们来分别分析下哪种情况下会分别使用:
(1):当在调用Handler的post方式时,会传入一个Runnable对象,此刻会调用第一种方式的run方法,如:

	public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

	private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

(2)当在创建Handler实例时,调用以下类型的Handler构造器,即传入一个Callback回调接口,如:

	public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

此时在调用dispatchMessage方法时就会选择第二种处理方式。
(3)第三种处理方式相信大家都比较熟悉了,这里也就不做过多的解释了。

接下来我们分析另外一个问题,之前不是说MessageQueue在获取消息的时候是一个死循环嘛,那这里应该如果结束掉这个死循环呢?当然Android肯定为我们提供了这样的方法,这里Looper有一个quit()方法,我们先看其源码:

	public void quit() {
		//调用是MessageQueue的quit方法
        mQueue.quit(false);
    }

	void quit(boolean safe) {
		//(1)mQuitAllowed变量
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }

        synchronized (this) {
            if (mQuitting) {
                return;
            }
            //(2)mQuitting变量
            mQuitting = true;

            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }

            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }

1、上面(1)处代码看到没,通过判断标记mQuitAllowed来决定该消息队列是否可以退出,然而当mQuitAllowed为fasle时抛出的异常竟然是”Main thread not allowed to quit.“。
还记得这个mQuitAllowed参数从什么地方赋值的,就是在调用Looper.prepare方式时,系统默认将其赋值为true(即prepare(true)),当在主线程中调用quit方法时将会抛出异常,原因是prepareMainLooper方法中赋的值是false(即prepare(false))。
2、继续往下看代码,可以发现quit的实质就是对mQuitting变量置位,这个mQuitting变量在MessageQueue的阻塞等待next方法中用做了判断条件,所以可以通过quit方法退出整个当前线程的loop循环。

到此Android的异步消息处理机制就分析的差不多了,接下来我们做一些总结。

4、总结和拓展

通过上面的源码分析我们用几张图来展示Handler,Message,Looper,MessageQueue直接的关系(图片来源于网络)。
图片来源于网络

接下来我们来看几个平时的常见问题:
1、Activity的runOnUiThread(Runnable action)方法

/**
  * Runs the specified action on the UI thread. If the current thread is the UI
  * thread, then the action is executed immediately. If the current thread is
  * not the UI thread, the action is posted to the event queue of the UI thread.
  * @param action the action to run on the UI thread
  */
    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

可以看出最终还是调用了Handler的post方法。

2、View的post(Runnable action)和postDelayed(Runnable action, long delayMillis)方法

	public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
        // Assume that post will succeed later
        ViewRootImpl.getRunQueue().post(action);
        return true;
    }

最终调用还是Handler的post方法。

3、Handler发送消息时最好通过obtainMessage()方法,而不是new Message,Handler的obtainMessage有多个重载的方法如obtainMessage(int what)、obtainMessage(int what, Object obj)等,因为这个方法中包含一个Message池,可以避免过多的分配内存。

4、在文章刚开始的示例中,我们在示例中标注的(3)部分有提及到创建Handler实例时可能会产生内存泄漏问题,这里的内存泄漏是由于Handler存在其所在Activity的引用,导致Activity无法被及时的回收。那这里应该如何操作呢?有两种方式:
(1)在Handler使用结束后,使用removeMessages或removeCallbacksAndMessages将对应的Message移除。
(2)将内部类Handler声明为静态类,静态类不持有外部类的对象,所以Activity可以被回收。

5、HandlerThread源码分析

很多人肯定会经常看到HandlerThread这个类,但是也不清楚和Handler到底有什么关系,所以今天我们就来分析一下该类源码,如下:

/**
 * 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;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    //可重写该方法,在Looper.loop之前处理一些逻辑问题
    protected void onLooperPrepared() {
    }
	//HandlerThread线程的run方法
    @Override
    public void run() {
        mTid = Process.myTid();
        //创建Looper对象和MessageQueue对象,需要在线程的start方法后执行
        Looper.prepare();
        synchronized (this) {
	        //获取Looper对象,唤起所有线程
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        //开始循环取消息
        Looper.loop();
        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()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    /**
     * Quits the handler thread's looper.
     * <p>
     * Causes the handler thread's looper to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     *
     * @see #quitSafely
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
	        //退出消息队列
            looper.quit();
            return true;
        }
        return false;
    }

    /**
     * Quits the handler thread's looper safely.
     * <p>
     * Causes the handler thread's looper to terminate as soon as all remaining messages
     * in the message queue that are already due to be delivered have been handled.
     * Pending delayed messages with due times in the future will not be delivered.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p>
     * 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.
     * </p>
     *
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     */
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

以上就是HandlerThread的整个源码,其实说白了HandlerThread就是Thread、Handler、Looper的组合,将这些统一封装在HandlerThread中,方便开发者使用。

接下来我们看一个HandlerThread的实例:

public class HandlerThreadActivity extends Activity {
    private HandlerThread mHandlerThread = null;
    private Handler mHandler = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initData();
    }

    private void initData() {
        mHandlerThread = new HandlerThread("HandlerThread");
        //必须在创建Handler之前调用start方法
        mHandlerThread.start();
        //将当前mHandlerThread子线程的Looper传入mHandler
        mHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
				//子线程发送消息
            }
        };
        
        //从主线程往子线程发送消息
        mThreadHandler.sendEmptyMessage(0);
    }
}

好啦,到此整个Android异步消息处理机制我们就完全分析结束了,相信大家已经对它很了解了,那今天就到这里啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪舞飞影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值