Android HandlerThread使用總結
來自: http://waylenw.github.io/Android/android-handler-thread-usage/
簡介
首先我們看到HandlerThread很快就會聯想到Handler。Android中Handler的使用,一般都在UI主線程中執行,因此在Handler接收消息后,處理消息時,不能做一些很耗時的操作,否則將出現ANR錯誤。
Android中專門提供了HandlerThread類,來解決該類問題。HandlerThread類是一個線程專門處理Hanlder的消息,依次從Handler的隊列中獲取信息,逐個進行處理,保證安全,不會出現混亂引發的異常。HandlerThread繼承于Thread,所以它本質就是個Thread。與普通Thread的差別就在于,它有個Looper成員變量。
在看看官方的對他的講解
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.
大致意思就是說HandlerThread可以創建一個帶有looper的線程。looper對象可以用于創建Handler類來進行來進行調度。接下來看看HandlerThread的源碼
package android.os;
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
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;
}線程run()方法當中先調用Looper.prepare()初始化Looper,最后調用Looper.loop(),這樣我們就在該線程當中創建好Looper。(注意:Looper.loop()方法默認是死循環).prepare()呢。
Handler原理
要理解Handler的原理,理解如下幾個概念即可茅塞頓開。
- Message 意為消息,發送到Handler進行處理的對象,攜帶描述信息和任意數據。
- MessageQueue 意為消息隊列,Message的集合。
- Looper 有著一個很難聽的中文名字,消息泵,用來從MessageQueue中抽取Message,發送給Handler進行處理。
- Handler 處理Looper抽取出來的Message。
Android 異步消息處理機制 讓你深入理解 Looper、Handler、Message三者關系
用法
HandlerThread thread = newHandlerThread("handler_thread");
thread.start();//必須要調用start方法
final Handlerhandler = newHandler(thread.getLooper()){其他api
//用于返回與該線程相關聯的Looper對象 thread.getLooper(); //獲得該線程的Id thread.getThreadId(); //結束當前的Looper 循環。 thread.quit(); //用于looper取出的消息處理 thread.run();
實例
效果圖
在以上效果圖中可以看到當我點擊按鈕之后,兩個藍色的方塊變成了圖片。在按鈕點擊事件中我添加了兩個下載圖片的任務(模擬情況下),并在加載完后替換控件的默認圖片。很明顯很可以看到是有先后順序的。在第一張圖片加載完后第二張圖片才會顯示。
MainActivity
public class MainActivity extends AppCompatActivity {
private HandlerThread handlerThread;
private ImageView imageView,imageView1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
imageView= (ImageView) findViewById(R.id.imageView);
imageView1= (ImageView) findViewById(R.id.imageView1);
handlerThread = new HandlerThread("MainActivity");
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper());
//點擊download開始進行下載
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.post(new MyRunable(1));
handler.post(new MyRunable(2));
}
});
}
class MyRunable implements Runnable {
int pos;
public MyRunable(int pos) {
this.pos = pos;
}
@Override
public void run() {
//模擬耗時
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (pos == 1) {
imageView.post(new Runnable() {
@Override
public void run() {
imageView.setBackgroundResource(R.mipmap.ic_launcher);
}
});
} else {
imageView.post(new Runnable() {
@Override
public void run() {
imageView1.setBackgroundResource(R.mipmap.ic_launcher);
}
});
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
handlerThread.quit();//停止Looper的循環
}
}布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.handlerthread.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@android:color/holo_blue_dark" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:background="@android:color/holo_blue_dark" />
</LinearLayout>
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="downLoad" />
</LinearLayout>總結
HandlerThread適合在只需要在一個工作線程(非UI線程)+任務的等待隊列的形式,優點是不會有堵塞,減少了對性能的消耗,缺點是不能同時進行多任務的處理,需要等待進行處理。處理效率較低。