一個(gè)handler對(duì)象中有對(duì)應(yīng)的線(xiàn)程隊(duì)列和消息隊(duì)列,如下示例線(xiàn)程隊(duì)列:
布局文件(很簡(jiǎn)單既绕,就兩個(gè)按鈕啄刹,一個(gè)TextView):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.austin.handlerstudy.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_start"
android:text="開(kāi)始" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_stop"
android:text="停止" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="第一條信息" />
</LinearLayout>
</ScrollView>
</LinearLayout>
public class MainActivity extends AppCompatActivity {
TextView tvInfo;
Button btnStart,btnStop;
Handler handler = new Handler();
MyTask task = new MyTask();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvInfo = findViewById(R.id.tv_info);
btnStart = findViewById(R.id.btn_start);
btnStop = findViewById(R.id.btn_stop);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.post(task);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.removeCallbacks(task);
}
});
}
class MyTask extends Thread{
@Override
public void run() {
tvInfo.append("\n received msg!");
handler.postDelayed(task,3000);
}
}
}
運(yùn)行時(shí)點(diǎn)擊start,就會(huì)每隔三秒打印一次msg凄贩,點(diǎn)擊stop后停止接收和打印誓军。這就是一個(gè)簡(jiǎn)單的線(xiàn)程隊(duì)列應(yīng)用的例子,但注意疲扎,此時(shí)調(diào)用的run方法昵时,其實(shí)沒(méi)有真正啟動(dòng)給一個(gè)子線(xiàn)程廓译,相當(dāng)于手動(dòng)調(diào)用了一次run方法而已,也就是說(shuō)所有消息的創(chuàng)建和處理都在主線(xiàn)程债查。
下面演示如何在主線(xiàn)程發(fā)消息由子線(xiàn)程處理:
public class Handler2Act extends AppCompatActivity {
private final String TAG = Handler2Act.class.getSimpleName();
MyHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_handler2);
Log.e(TAG,"MainActivity所在線(xiàn)程名:"+Thread.currentThread().getName()+" 線(xiàn)程Id"+Thread.currentThread().getId());
//HandlerThread實(shí)現(xiàn)了使用Looper來(lái)處理消息隊(duì)列的功能
HandlerThread handlerThread = new HandlerThread("my handler thread");
handlerThread.start();
//getLooper()一定要寫(xiě)在線(xiàn)程start方法之后
mHandler = new MyHandler(handlerThread.getLooper());
Message msg = mHandler.obtainMessage();
msg.arg1 = 5;
msg.sendToTarget();//發(fā)送消息到創(chuàng)建該消息的handler的looper所在線(xiàn)程上
}
class MyHandler extends Handler{
MyHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.e(TAG,"MyHandler所在線(xiàn)程名字:"+Thread.currentThread().getName()+" 線(xiàn)程id:"+Thread.currentThread().getId());
}
}
}
可以發(fā)現(xiàn)handlerMessage方法運(yùn)行在了子線(xiàn)程非区。
HandlerThread優(yōu)點(diǎn):
- HandlerThread 內(nèi)部實(shí)現(xiàn)了一個(gè)Handler輪循器,可以使用它而非主線(xiàn)程中自帶的輪循器從而避免主線(xiàn)程任務(wù)過(guò)多和壓力過(guò)大導(dǎo)致的流暢度不佳盹廷。
- 可以處理多個(gè)任務(wù)征绸,開(kāi)啟一個(gè)線(xiàn)程起到多個(gè)線(xiàn)程的作用。因?yàn)槠鋬?nèi)部Handler.handleMessage的執(zhí)行俄占,一定在它的Looper的線(xiàn)程中管怠。(Looper共享)
舉例:HandlerThread與Camera能夠Looper共享。
所以Handler機(jī)制(消息機(jī)制)不僅僅是能夠?qū)崿F(xiàn)主子線(xiàn)程通訊缸榄,還能實(shí)現(xiàn)資源共享(Looper共享)渤弛。