一、HandlerThread 的介绍及使用举例
HandlerThread 是什么鬼?其本质就是一个线程,但是 HandlerThread 在启动的时候会帮我们准备好一个 Looper, 并供外界使用,说白了就是使我们在子线程中更方便的使用 Handler,比如没有 HandlerThread 我们要在子线程使用 Handler,写法如下:
- private Handler mHandler;
- @Override
- public void run() {
- super.run();
- Looper.prepare();
- mHandler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- }
- };
- Looper.loop();
- }
有了 HandlerThread 就不用我们自己管理 Looper 了,至于为什么分析源码的时候就明白了。
HandlerThread 使用简单介绍:
首先我们要初始化 HandlerThread 然后调用其 start 方法,也就是开启线程:
- mHandlerThread = new HandlerThread("mHandlerThread"); //这里的mHandlerThread其实就是线程的名字
- mHandlerThread.start();
接下来初始化一个 Handler 并且将 mHandlerThread 中的 Looper 作为构造函数参数传递给 Handler:
- 1 mHandler = new Handler(mHandlerThread.getLooper())
这样就保证了 Hnadler 运行在子线程。并且需要在适合的时机调用 HandlerThread 的 quit 方法或 quitSafely 方法,如 Activity 销毁的时候:
- @Override
- protected void onDestroy() {
- //
- super.onDestroy();
- //释放资源
- mHandlerThread.quit();
- }
quit() 与 quitSafely() 方法比较 (这里只说一些结论,源码可以自己查看):
相同点:
调用之后 MessageQueue 消息队列均不在接受新的消息加入队列。
不同点:
quit 方法把 MessageQueue 消息池中所有的消息全部清空。quitSafely 方法只会清空 MessageQueue 消息池中所有的延迟消息(延迟消息是指通过 sendMessageDelayed 或 postDelayed 等方法发送的消息),非延迟消息则不清除继续派发出去让 Handler 去处理。
接下来我们完整看一下 HandlerThread 例子源码:
- public class MainActivity extends Activity {
- private HandlerThread mHandlerThread;
- private Handler mHandler;
- private boolean flag;
- //
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mHandlerThread = new HandlerThread("mHandlerThread");
- mHandlerThread.start();
- mHandler = new Handler(mHandlerThread.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- //
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if(flag){
- Log.i("HandlerThread", "更新:"+new Random().nextInt(1000));
- }
- mHandler.sendEmptyMessage(1);
- }
- };
- }
- @Override
- protected void onResume() {
- //
- super.onResume();
- flag = true;
- mHandler.sendEmptyMessage(1);
- }
- @Override
- protected void onPause() {
- //
- super.onPause();
- flag = false;
- }
- @Override
- protected void onDestroy() {
- //
- super.onDestroy();
- //释放资源
- mHandlerThread.quit();
- }
- }
运行程序就会在控制台看到每隔两秒有 Log 打出。至于 HandlerThrea 的使用就到此为止了,看懂上面小例子就差不多了。
二、HandlerThread 的源码分析
HandlerThread 源码非常简短,出去注释不到 100 行,这里就直接全部贴出来了:
- 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.
- */
- protected void onLooperPrepared() {}
- @Override public void run() {
- mTid = Process.myTid();
- Looper.prepare();
- synchronized(this) {
- 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;
- }
- public boolean quit() {
- Looper looper = getLooper();
- if (looper != null) {
- looper.quit();
- return true;
- }
- return false;
- }
- 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;
- }
- }
看第一行就知道了其本质就是一个线程。
6-9 行以及 17-20 行构造函数,也很简单,就是初始化的时候我们可以定义线程名字,还可以传入线程优先级。
初始化完成,紧接着调用 start() 开发线程就会执行 run 方法逻辑。
30-41 行代码,最重要的就是调用 Looper.prepare() 以及 Looper.loop() 方法为我们在子线程准备好一个 Looper。并且用变量 mLooper 记录,调用 getLooper() 方法的时候返回。
但是,细心的你肯定发现 run() 方法中有个 notifyAll(),getLooper() 中有个 wait() 为什么要加这些鸟玩意?
大家发现没在 HandlerThread 例子中 Handler 的创建是在主线程完成的,创建的时候需要调用 HandlerThread 的 getLooper() 获取 mLooper 作为参数传递给 Handler 的构造函数,而 Looper 的创建是在子线程中创建的,这里就有线程同步问题了,比如我们调用 getLooper() 的时候 HandlerThread 中 run() 方法还没执行完,mLooper 变量还未赋值,此时就执行了 wait() 等待逻辑,一直等到 run() 方法中 mLooper 被赋值,之后立即执行 notifyAll(),然后 getLooper() 就可以正确返回 mLooper 了。
明白了吧,不明的话这里需要花些时间好好理解下,好了源码主要部分就分析完了,看到这里相信你对 HandlerThread 有了一定的了解了。
HandlerThread 还是比较简单理解的,好了,本篇到此为止,希望对你有帮助。
来源: http://www.cnblogs.com/leipDao/p/8005520.html