【安卓笔记】HandlerThread源码剖析
package com.example.handlethreaddemo; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.util.Log; public class MainActivity extends Activity { private Looper mLooper; private MyHandler mHandler; private static final String TAG = "MainActivity"; private static class MyHandler extends Handler { public MyHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: Log.i(TAG, "当前线程是"+Thread.currentThread().getName()+",TEST 1"); break; case 2: Log.i(TAG, "TEST 2"); break; } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建HandlerThread对象 HandlerThread myHandleThread = new HandlerThread("HandlerThread<子线程>"); //启动HandlerThread---->内部将启动消息循环 myHandleThread.start(); //获取Looper mLooper = myHandleThread.getLooper(); //构造Handler,传入子线程中的Looper mHandler = new MyHandler(mLooper); /* * 注:经过上述步骤,Handler将绑定子线程的Looper和MessageQueue. * 也就是说handleMessage最终由子线程调用 * */ mHandler.sendEmptyMessage(1); Log.i(TAG,"当前线程是:"+Thread.currentThread().getName()); } }
使用HandlerThread内部提供的Looper对象构造Handler对象,然后在ui线程中向Handler发送消息。log日志如下:
int mPriority;//优先级 int mTid = -1;//线程标志 Looper mLooper;//消息循环
可通过构造器注入线程优先级,默认优先级为Process.THREAD_PRIORITY_DEFAULT
public HandlerThread(String name, int priority) { super(name); mPriority = priority; }
核心逻辑为run方法(复写Thread类的run方法):
public void run() { mTid = Process.myTid(); Looper.prepare();//创建Looper对象 synchronized (this) { mLooper = Looper.myLooper();//获取与本线程绑定的Looper notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared();//回调接口,默认为空实现。 Looper.loop();//启动消息循环--->may be blocked mTid = -1; }
外界可通过getLooper方法获取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();//异步等待Looper准备好 } catch (InterruptedException e) { } } } return mLooper; }
public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit();//内部调用looper类的quit return true; } return false; }
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)); }
然后通过Looper.myLooper方法返回与本线程绑定的Looper,正是刚创建的Looper:
public static Looper myLooper() { return sThreadLocal.get(); }
Looper.loop方法将启动消息循环,不断从其内部封装的消息队列MessageQueue中取出消息,交由Handler执行。
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(); } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。