編輯: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(); }
實現很簡單,在目標線程內如下配置
明白上面的實現步驟,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的原理,理解如下幾個概念即可茅塞頓開。
HandlerThread使用起來很容易,首先需要進行初始化。
private Handler mHandler; private LightTaskManager() { HandlerThread workerThread = new HandlerThread("LightTaskThread"); workerThread.start(); mHandler = new Handler(workerThread.getLooper()); }
注意:上面的workerThread.start();必須要執行。
至於如何使用HandlerThread來執行任務,主要是調用Handler的API
通過包裹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沒有必要設置這麼高的優先級,因而需要我們降低其優先級。
以上的這些優先級都是可以在程序中設置的,除此之外還有不可控的優先級均有系統進行自動調整。
最通用的就是在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,或者文件寫入操作。
本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃! 自動化測試時下在產品測試上有著非常重要的作用。實現測試自動化有多種
在android上,視頻/音頻流直播是極少有人關注的一部分。每當我們討論流媒體,RTMP(Real Time Messaging Protocol)是不可或缺的。
本文由碼農網 – 蘇耀東原創,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃! 簡介 本文是參考google官方發布的MVP架構demo以及前人對M
除了Android系統自帶的Button按鈕以外,還提供了帶圖標的按鈕ImageButton 要制作帶圖標的按鈕,首先要在布局文件中定義ImageButton,然