Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android資訊 >> Android 中的 HandlerThread 詳解

Android 中的 HandlerThread 詳解

編輯:Android資訊

HandlerThread是Android API提供的一個便捷的類,使用它我們可以快速的創建一個帶有Looper的線程,有了Looper這個線程,我們又可以生成Handler,那麼 HandlerThread是什麼,可以做什麼呢,有哪些奇技淫巧可以被我們利用呢?

實現原理

在介紹原理之前,我們先使用普通的Thread來創建一個Handler,創建的過程大致如下:

 Handler mHandler;
private void createManualThreadWithHandler() {
  new Thread() {
      @Override
        public void run() {
            super.run();
            Looper.prepare();
            mHandler = new Handler(Looper.myLooper());
            Looper.loop();
        }
    }.start();
}

實現很簡單,在目標線程內如下配置

  • 調用Looper.prepare 創建與當前線程綁定的Looper實例
  • 使用上面創建的Looper生成Handler實例
  • 調用Looper.loop()實現消息循環

明白上面的實現步驟,HandlerThread的實現也就簡單了,其實現為:

 @Override
public void run() {
  mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
      mLooper = Looper.myLooper();
      notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

確實很簡單,無需贅述。

Handler原理

要理解Handler的原理,理解如下幾個概念即可茅塞頓開。

  • Message 意為消息,發送到Handler進行處理的對象,攜帶描述信息和任意數據。
  • MessageQueue 意為消息隊列,Message的集合。
  • Looper 有著一個很難聽的中文名字,消息泵,用來從MessageQueue中抽取Message,發送給Handler進行處理。
  • Handler 處理Looper抽取出來的Message。

如何使用

HandlerThread使用起來很容易,首先需要進行初始化。

 private Handler mHandler;
private LightTaskManager() {
    HandlerThread workerThread = new HandlerThread("LightTaskThread");
    workerThread.start();
    mHandler = new Handler(workerThread.getLooper());
}

注意:上面的workerThread.start();必須要執行。

至於如何使用HandlerThread來執行任務,主要是調用Handler的API

  • 使用post方法提交任務,postAtFrontOfQueue將任務加入到隊列前端,postAtTime指定時間提交任務,postDelayed延後提交任務。
  • 使用sendMessage方法可以發送消息,sendMessageAtFrontOfQueue將該消息放入消息隊列前端,sendMessageAtTime 指定時間發送消息,sendMessageDelayed延後提交消息。

通過包裹Handler API,我們可以實現如下代碼(僅post相關方法):

 public void post(Runnable run) {
    mHandler.post(run);
}

public void postAtFrontOfQueue(Runnable runnable) {
    mHandler.postAtFrontOfQueue(runnable);
}

public void postDelayed(Runnable runnable, long delay) {
    mHandler.postDelayed(runnable, delay);
}

public void postAtTime(Runnable runnable, long time) {
    mHandler.postAtTime(runnable, time);
}

控制優先級

了解到如何使用之外,關於HandlerThread的使用需要上升一個界別,那就是優化。這裡的優化主要是合理調整HandlerThread的優先級。

HandlerThread的默認優先級是Process.THREAD_PRIORITY_DEFAULT,具體值為0。線程的優先級的取值范圍為-20到19。優先級高的獲得的CPU資源更多,反之則越少。-20代表優先級最高,19最低。0位於中間位置,但是作為工作線程的HandlerThread沒有必要設置這麼高的優先級,因而需要我們降低其優先級。

可控制的優先級

  • THREAD_PRIORITY_DEFAULT,默認的線程優先級,值為0。
  • THREAD_PRIORITY_LOWEST,最低的線程級別,值為19。
  • THREAD_PRIORITY_BACKGROUND 後台線程建議設置這個優先級,值為10。
  • THREAD_PRIORITY_MORE_FAVORABLE 相對THREAD_PRIORITY_DEFAULT稍微優先,值為-1。
  • THREAD_PRIORITY_LESS_FAVORABLE 相對THREAD_PRIORITY_DEFAULT稍微落後一些,值為1。

以上的這些優先級都是可以在程序中設置的,除此之外還有不可控的優先級均有系統進行自動調整。

如何修改權限

最通用的就是在run方法中,加入合理的設置優先級代碼,比如

 Runnable run = new Runnable() {
    @Override
    public void run() {
        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    }
};
LightTaskManager.getInstance().post(run);

上述方法不僅適用於HandlerThread,也可以適用於其他的線程。

除此之外,HandlerThread的構造方法也提供了設置優先級的功能。用法如下:

 HandlerThread workerThread = new HandlerThread("LightTaskThread", Process.THREAD_PRIORITY_BACKGROUND);

關於設置優先級,系統的AsyncTask已經開始進行了默認設置,將線程的優先級設置成THREAD_PRIORITY_BACKGROUND了。

 public AsyncTask() {
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            Result result = doInBackground(mParams);
            Binder.flushPendingCommands();
            return postResult(result);
        }
    };
}

關於Android中線程的調度詳情,請參考 剖析Android中進程與線程調度之nice

應用場景

我們可以使用HandlerThread處理本地IO讀寫操作(數據庫,文件),因為本地IO操作大多數的耗時屬於毫秒級別,對於單線程 + 異步隊列的形式 不會產生較大的阻塞。因此在這個HandlerThread中不適合加入網絡IO操作。

對於本地IO讀取操作,我們可以使用postAtFrontOfQueue方法,快速將讀取操作加入隊列前端執行,必要時返回給主線程更新 UI。示例場景,從數據庫中讀取數據展現在ListView中。注意讀取也是需要花費一定時間,推薦在數據展示之前有必要的用戶可感知進度提示。

對於本地IO寫操作,根據具體情況,選擇post或者postDelayed方法執行。比如SharedPreference commit,或者文件寫入操作。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved