今天帶給大家的文章是透過實例程式碼分析Android中HandlerThread的用法以及步驟,需要的朋友參考學習下吧。
HandlerThread 簡介:
我們知道Thread執行緒是一次性消費品,當Thread執行緒執行完一個耗時的任務之後,執行緒就會被自動銷毀了。如果此時我又有一
個耗時任務需要執行,我們必須重新建立執行緒去執行該耗時任務。然而,這樣就存在一個效能問題:多次建立和銷毀執行緒是很耗
系統資源的。為了了解這個問題,我們可以自行建立一個循環執行緒Looper Thread,當有耗時任務投放到該循環執行緒時,執行緒執行耗
時任務,執行完後循環執行緒處於等待狀態,直到下一個新的耗時任務被放進來。這樣一來就避免了多次創建Thread線程導致的
效能問題了。也許你可以自己去建立一個循環線程,但我可以告訴你一個好消息,Aandroid SDK中其實已經有一個循環線程的框架
了。此時你只需要掌握其如何使用的就ok啦!當然就是我們今天的主角HandlerThread!接下來請HandlerThread上場,鼓掌~~
HandlerThread的父類是Thread,因此HandlerThread其實是一個線程,只不過其內部幫你實現了一個Looper的循環而已。那我們
先來了解Handler是怎麼使用的吧!
HandlerThread使用步驟:
1.建立實例物件
HandlerThread handlerThread = new HandlerThread("handlerThread");
以上參數可以任意字串,參數的作用主要是標記目前執行緒的名字。
2.啟動HandlerThread執行緒
handlerThread.start();
到此,我們就建構完一個循環執行緒了。那你可能會懷疑,那我怎麼將一個耗時的非同步任務投放到HandlerThread執行緒中去執行呢?當然是有辦法的,接下來看第三部。
3.建構循環訊息處理機制
Handler subHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //实现自己的消息处理 return true; } });
第三個步驟建立一個Handler對象,將上面HandlerThread中的looper物件最為Handler的參數,然後重寫Handler的Callback介面類別中的
handlerMessage方法來處理耗時任務。
總結:以上三步驟不能亂,必須嚴格依照步驟來。到此,我們就可以呼叫subHandler以傳送訊息的形式傳送耗時任務到執行緒
HandlerThread中去執行。言下之意就是subHandler中Callback介面類別中的handlerMessage方法其實是在工作執行緒中執行的。
HandlerThread實例:
package com.example.handlerthread; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private Handler mSubHandler; private TextView textView; private Button button; private Handler.Callback mSubCallback = new Handler.Callback() { //该接口的实现就是处理异步耗时任务的,因此该方法执行在子线程中 @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 0: Message msg1 = new Message(); msg1.what = 0; msg1.obj = java.lang.System.currentTimeMillis(); mUIHandler.sendMessage(msg1); break; default: break; } return false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); button = (Button) findViewById(R.id.button); HandlerThread workHandle = new HandlerThread("workHandleThread"); workHandle.start(); mSubHandler = new Handler(workHandle.getLooper(), mSubCallback); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //投放异步耗时任务到HandlerThread中 mSubHandler.sendEmptyMessage(0); } }); } }
HandlerThread原始碼分析
/** * 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; //当前线程id int mTid = -1; //当前线程持有的Looper对象 Looper mLooper; //构造方法 public HandlerThread(String name) { //调用父类默认的方法创建线程 super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } //带优先级参数的构造方法 public HandlerThread(String name, int priority) { super(name); mPriority = priority; } ............... }
public class HandlerThread extends Thread { /** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { } @Override public void run() { //获得当前线程的id mTid = Process.myTid(); //准备循环条件 Looper.prepare(); //持有锁机制来获得当前线程的Looper对象 synchronized (this) { mLooper = Looper.myLooper(); //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait notifyAll(); } //设置当前线程的优先级 Process.setThreadPriority(mPriority); //该方法实现体是空的,子类可以实现该方法,作用就是在线程循环之前做一些准备工作,当然子类也可以不实现。 onLooperPrepared(); //启动loop 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() { //如果线程不是存活的,则直接返回null if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. //如果线程已经启动,但是Looper还未创建的话,就等待,知道Looper创建成功 synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; }
总结:在获得mLooper对象的时候存在一个同步的问题,只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值。这里等待方法wait和run方法中的notifyAll方法共同完成同步问题。
quit结束当前线程的循环
/** * 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; } //安全退出循环 public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; }
分析:以上有两种让当前线程退出循环的方法,一种是安全的,一中是不安全的。至于两者有什么区别? quitSafely方法效率比quit方法标率低一点,但是安全。具体选择哪种就要看具体项目了。
总结:
1.HandlerThread适用于构建循环线程。
2.在创建Handler作为HandlerThread线程消息执行者的时候必须调用start方法之后,因为创建Handler需要的Looper参数是从HandlerThread类中获得,而Looper对象的赋值又是在HandlerThread的run方法中创建。
相信看了这些案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
相关阅读:
以上是HandlerThread源碼詳解之Android實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!