Android后臺(tái)線(xiàn)程和UI線(xiàn)程通訊實(shí)例
本節(jié)向你展示如何在任務(wù)中發(fā)送數(shù)據(jù)給UI線(xiàn)程里的對(duì)象,這個(gè)特性允許你在后臺(tái)線(xiàn)程工作,完了在UI線(xiàn)程展示結(jié)果。
在UI線(xiàn)程定義一個(gè)Handler
Handler是Android系統(tǒng)線(xiàn)程管理框架里的一部分。一個(gè)Handler對(duì)象接收消息,并且運(yùn)行代碼來(lái)處理消息。正常情況下,你為新線(xiàn)程創(chuàng)建Handler,但你也可以為已有的線(xiàn)程創(chuàng)建一個(gè)Handler.當(dāng)你連接Handler到UI線(xiàn)程時(shí),處理消息的代碼會(huì)在UI線(xiàn)程上運(yùn)行.
在創(chuàng)建線(xiàn)程池的類(lèi)的構(gòu)造器里實(shí)例化Handler對(duì)象,保存在全局變量里。用Handler(Looper)方法實(shí)例化,連接到UI線(xiàn)程,構(gòu)造方法使用Looper對(duì)象,也是Android系統(tǒng)線(xiàn)程管理框架里的一部分.Looper類(lèi)有一個(gè)靜態(tài)方法getMainLooper()可以獲取UI線(xiàn)程的Looper對(duì)象。如:
private PhotoManager() {
...
// Defines a Handler object that's attached to the UI thread
mHandler = new Handler(Looper.getMainLooper()) {
...
在Handler里,覆蓋handleMessage()。Android系統(tǒng)會(huì)在Handler管理的線(xiàn)程收到新消息時(shí),調(diào)用該方法。一個(gè)指定線(xiàn)程的所有Handler對(duì)象都會(huì)收到相同的消息。
/*
* handleMessage() defines the operations to perform when
* the Handler receives a new Message to process.
*/
@Override
public void handleMessage(Message inputMessage) {
// Gets the image task from the incoming Message object.
PhotoTask photoTask = (PhotoTask) inputMessage.obj;
...
}
...
}
}
從任務(wù)里移動(dòng)數(shù)據(jù)到UI線(xiàn)程
要從后臺(tái)線(xiàn)程的任務(wù)里移動(dòng)數(shù)據(jù)到UI線(xiàn)程的對(duì)象,先保存引用到數(shù)據(jù)和任務(wù)對(duì)象的UI對(duì)象里,接下來(lái)把任務(wù)對(duì)象和狀態(tài)碼傳給Handler對(duì)象。在這個(gè)對(duì)象里,發(fā)送一個(gè)包含狀態(tài) 和任務(wù)對(duì)象的消息給Handler.因?yàn)镠andler在UI線(xiàn)程上運(yùn)行,它可以移動(dòng)數(shù)據(jù)給UI對(duì)象。
在任務(wù)對(duì)象里存儲(chǔ)數(shù)據(jù)
如,這是一個(gè)Runnable,運(yùn)行在后臺(tái)線(xiàn)程,它解析Bitmap,并保存到它的父對(duì)象。Runnable同時(shí)保存狀態(tài)碼DECODE_STATE_COMPLETED。
// A class that decodes photo files into Bitmaps
class PhotoDecodeRunnable implements Runnable {
...
PhotoDecodeRunnable(PhotoTask downloadTask) {
mPhotoTask = downloadTask;
}
...
// Gets the downloaded byte array
byte[] imageBuffer = mPhotoTask.getByteBuffer();
...
// Runs the code for this task
public void run() {
...
// Tries to decode the image buffer
returnBitmap = BitmapFactory.decodeByteArray(
imageBuffer,
0,
imageBuffer.length,
bitmapOptions
);
...
// Sets the ImageView Bitmap
mPhotoTask.setImage(returnBitmap);
// Reports a status of "completed"
mPhotoTask.handleDecodeState(DECODE_STATE_COMPLETED);
...
}
...
}
...
PhotoTask還包含一個(gè)ImageView引用,用來(lái)顯示Bitmap.盡管引用Bitmap和ImageView是在同一個(gè)對(duì)象里,但因?yàn)椴皇窃赨I線(xiàn)程,你不能直接讓ImageView顯示Bitmap.
沿對(duì)象層次逐級(jí)發(fā)送狀態(tài)
PhotoTask持有解碼的數(shù)據(jù)和顯示數(shù)據(jù)的View對(duì)象的引用,它從PhotoDecodeRunnable接收到狀態(tài)碼,并且沿著線(xiàn)程池里引用的對(duì)象和Handler實(shí)例傳送。
public class PhotoTask {
...
// Gets a handle to the object that creates the thread pools
sPhotoManager = PhotoManager.getInstance();
...
public void handleDecodeState(int state) {
int outState;
// Converts the decode state to the overall state.
switch(state) {
case PhotoDecodeRunnable.DECODE_STATE_COMPLETED:
outState = PhotoManager.TASK_COMPLETE;
break;
...
}
...
// Calls the generalized state method
handleState(outState);
}
...
// Passes the state to PhotoManager
void handleState(int state) {
/*
* Passes a handle to this task and the
* current state to the class that created
* the thread pools
*/
sPhotoManager.handleState(this, state);
}
...
}
移動(dòng)數(shù)據(jù)到UI
PhotoManager從PhotoTask對(duì)象接收到狀態(tài)碼和PhotoTask對(duì)象的句柄。因?yàn)闋顟B(tài)是TASK_COMPLETE,創(chuàng)建一個(gè)包含狀態(tài)和任務(wù)對(duì)象的Message,發(fā)送給Handler。
public class PhotoManager {
...
// Handle status messages from tasks
public void handleState(PhotoTask photoTask, int state) {
switch (state) {
...
// The task finished downloading and decoding the image
case TASK_COMPLETE:
/*
* Creates a message for the Handler
* with the state and the task object
*/
Message completeMessage =
mHandler.obtainMessage(state, photoTask);
completeMessage.sendToTarget();
break;
...
}
...
}
最終,Handler.handleMessage()為每個(gè)進(jìn)來(lái)的Message檢查狀態(tài)碼。如果狀態(tài)碼是TASK_COMPLETE,任務(wù)就是完成了,Message里的PhotoTask對(duì)象包含Bitmap和ImageView.因?yàn)镠andler.handleMessage()運(yùn)行在UI線(xiàn)程,它可以安全地為ImageView設(shè)置Bitmap.
- Java并發(fā)編程線(xiàn)程間通訊實(shí)現(xiàn)過(guò)程詳解
- Java多線(xiàn)程通訊之wait,notify的區(qū)別詳解
- 淺談Java多線(xiàn)程實(shí)現(xiàn)及同步互斥通訊
- Python3 socket即時(shí)通訊腳本實(shí)現(xiàn)代碼實(shí)例(threading多線(xiàn)程)
- python socket多線(xiàn)程通訊實(shí)例分析(聊天室)
- android使用handler ui線(xiàn)程和子線(xiàn)程通訊更新ui示例
- JAVA多線(xiàn)程間通訊常用實(shí)現(xiàn)方法解析
相關(guān)文章
淺析Android手機(jī)衛(wèi)士之手機(jī)實(shí)現(xiàn)短信指令獲取位置
這篇文章主要介紹了淺析Android手機(jī)衛(wèi)士之手機(jī)實(shí)現(xiàn)短信指令獲取位置的相關(guān)資料,需要的朋友可以參考下2016-04-04Flow轉(zhuǎn)LiveData數(shù)據(jù)丟失原理詳解
這篇文章主要為大家介紹了Flow轉(zhuǎn)LiveData數(shù)據(jù)丟失原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Android不壓縮圖片實(shí)現(xiàn)高清加載巨圖實(shí)例
這篇文章主要為大家介紹了Android不壓縮圖片實(shí)現(xiàn)高清加載巨圖實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Android中button實(shí)現(xiàn)onclicklistener事件的兩種方式
本文介紹下Android中button實(shí)現(xiàn)onclicklistener事件的兩種方法,感興趣的朋友可以參考下2013-04-04Android WebView線(xiàn)性進(jìn)度條實(shí)例詳解
這篇文章主要介紹了Android WebView線(xiàn)性進(jìn)度條實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-01-01Android實(shí)現(xiàn)指定時(shí)間定時(shí)觸發(fā)方法
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)指定時(shí)間定時(shí)觸發(fā)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05Android中Fragment的加載方式與數(shù)據(jù)通信詳解
本文主要介紹了Android中Fragment的加載方式與數(shù)據(jù)通信的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法
這篇文章主要為大家詳細(xì)介紹了Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07android實(shí)現(xiàn)接通和掛斷電話(huà)
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)接通和掛斷電話(huà)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05