前言
-
多線程的應(yīng)用在Android開發(fā)中是非常常見的,常用方法主要有:
- 繼承Thread類
- 實現(xiàn)Runnable接口
- Handler
- AsyncTask
- HandlerThread
今天,我將介紹多線程其中一種常見用法:
HandlerThread
的具體使用
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實例教程)
Android多線程:實現(xiàn)Runnable接口使用(含實例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
目錄
1. 簡介
更加具體請看文章:Android多線程:這是一份全面 & 詳細(xì)的HandlerThread學(xué)習(xí)指南
2. 使用步驟
-
HandlerThread
的本質(zhì):繼承Thread
類 & 封裝Handler
類 -
HandlerThread
的使用步驟分為5步
// 步驟1:創(chuàng)建HandlerThread實例對象
// 傳入?yún)?shù) = 線程名字,作用 = 標(biāo)記該線程
HandlerThread mHandlerThread = new HandlerThread("handlerThread");
// 步驟2:啟動線程
mHandlerThread.start();
// 步驟3:創(chuàng)建工作線程Handler & 復(fù)寫handleMessage()
// 作用:關(guān)聯(lián)HandlerThread的Looper對象、實現(xiàn)消息處理操作 & 與其他線程進行通信
// 注:消息處理操作(HandlerMessage())的執(zhí)行線程 = mHandlerThread所創(chuàng)建的工作線程中執(zhí)行
Handler workHandler = new Handler( mHandlerThread.getLooper() ) {
@Override
public boolean handleMessage(Message msg) {
...//消息處理
return true;
}
});
// 步驟4:使用工作線程Handler向工作線程的消息隊列發(fā)送消息
// 在工作線程中,當(dāng)消息循環(huán)時取出對應(yīng)消息 & 在工作線程執(zhí)行相關(guān)操作
// a. 定義要發(fā)送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的標(biāo)識
msg.obj = "B"; // 消息的存放
// b. 通過Handler發(fā)送消息到其綁定的消息隊列
workHandler.sendMessage(msg);
// 步驟5:結(jié)束線程,即停止線程的消息循環(huán)
mHandlerThread.quit();
3. 實例講解
下面,我將用一個實例講解HandlerThread
該如何使用
3.1 實例說明
- 點擊按鈕實現(xiàn)延遲操作
- 最終更新UI組件
3.2 具體實現(xiàn)
建議先下載源碼再閱讀:Carson_Ho的Github:HandlerThread
- 主布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:gravity="center"
tools:context="com.example.carson_ho.handler_learning.MainActivity">
<TextView
android:id="@+id/text1"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="測試結(jié)果" />
<Button
android:id="@+id/button1"
android:layout_centerInParent="true"
android:layout_below="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點擊延遲1s + 顯示我愛學(xué)習(xí)"/>
<Button
android:id="@+id/button2"
android:layout_centerInParent="true"
android:layout_below="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點擊延遲3s + 顯示我不愛學(xué)習(xí)"/>
<Button
android:id="@+id/button3"
android:layout_centerInParent="true"
android:layout_below="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="結(jié)束線程的消息循環(huán)"/>
</RelativeLayout>
- 主代碼文件:MainActivity.java
public class MainActivity extends AppCompatActivity {
Handler mainHandler,workHandler;
HandlerThread mHandlerThread;
TextView text;
Button button1,button2,button3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 顯示文本
text = (TextView) findViewById(R.id.text1);
// 創(chuàng)建與主線程關(guān)聯(lián)的Handler
mainHandler = new Handler();
/**
* 步驟1:創(chuàng)建HandlerThread實例對象
* 傳入?yún)?shù) = 線程名字,作用 = 標(biāo)記該線程
*/
mHandlerThread = new HandlerThread("handlerThread");
/**
* 步驟2:啟動線程
*/
mHandlerThread.start();
/**
* 步驟3:創(chuàng)建工作線程Handler & 復(fù)寫handleMessage()
* 作用:關(guān)聯(lián)HandlerThread的Looper對象、實現(xiàn)消息處理操作 & 與其他線程進行通信
* 注:消息處理操作(HandlerMessage())的執(zhí)行線程 = mHandlerThread所創(chuàng)建的工作線程中執(zhí)行
*/
workHandler = new Handler(mHandlerThread.getLooper()){
@Override
// 消息處理的操作
public void handleMessage(Message msg)
{
//設(shè)置了兩種消息處理操作,通過msg來進行識別
switch(msg.what){
// 消息1
case 1:
try {
//延時操作
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通過主線程Handler.post方法進行在主線程的UI更新操作
mainHandler.post(new Runnable() {
@Override
public void run () {
text.setText("我愛學(xué)習(xí)");
}
});
break;
// 消息2
case 2:
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mainHandler.post(new Runnable() {
@Override
public void run () {
text.setText("我不喜歡學(xué)習(xí)");
}
});
break;
default:
break;
}
}
};
/**
* 步驟4:使用工作線程Handler向工作線程的消息隊列發(fā)送消息
* 在工作線程中,當(dāng)消息循環(huán)時取出對應(yīng)消息 & 在工作線程執(zhí)行相關(guān)操作
*/
// 點擊Button1
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 通過sendMessage()發(fā)送
// a. 定義要發(fā)送的消息
Message msg = Message.obtain();
msg.what = 1; //消息的標(biāo)識
msg.obj = "A"; // 消息的存放
// b. 通過Handler發(fā)送消息到其綁定的消息隊列
workHandler.sendMessage(msg);
}
});
// 點擊Button2
button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 通過sendMessage()發(fā)送
// a. 定義要發(fā)送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的標(biāo)識
msg.obj = "B"; // 消息的存放
// b. 通過Handler發(fā)送消息到其綁定的消息隊列
workHandler.sendMessage(msg);
}
});
// 點擊Button3
// 作用:退出消息循環(huán)
button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHandlerThread.quit();
}
});
}
}
- 運行結(jié)果
4. 特別注意點
在HandlerThread中,有2個問題需注意的:內(nèi)存泄漏 & 連續(xù)發(fā)送消息
4.1 內(nèi)存泄露
- 在上面的例子中,出現(xiàn)了嚴(yán)重的警告:
In Android, Handler classes should be static or leaks might occur.
- 即造成了嚴(yán)重的內(nèi)存泄漏,關(guān)于Handler的內(nèi)存泄露請看文章:Android 內(nèi)存泄露:詳解 Handler 內(nèi)存泄露的原因
4.2 連續(xù)發(fā)送消息
- 當(dāng)你連續(xù)點擊3下時,發(fā)現(xiàn)并無按照最新點擊的按鈕操作顯示,而是按順序的一個個顯示出來
- 原因:使用
HandlerThread
時只是開了一個工作線程,當(dāng)你點擊了n
下后,只是將n
個消息發(fā)送到消息隊列MessageQueue
里排隊,等候派發(fā)消息給Handler再進行對應(yīng)的操作
5. 總結(jié)
- 本文主要介紹了多線程
HandlerThread
的用法 - 下一篇文章我將對講解
Android
多線程的相關(guān)知識,感興趣的同學(xué)可以繼續(xù)關(guān)注Carson_Ho的簡書
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實例教程)
Android多線程:實現(xiàn)Runnable接口使用(含實例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
歡迎關(guān)注Carson_Ho的簡書
不定期分享關(guān)于安卓開發(fā)的干貨,追求短、平、快,但卻不缺深度。