Android開(kāi)發(fā)之子線程操作UI的幾種方法
在Android項(xiàng)目中經(jīng)常有碰到這樣的問(wèn)題,在子線程中完成耗時(shí)操作之后要更新UI,下面就自己經(jīng)歷的一些項(xiàng)目總結(jié)一下更新的方法:
在看方法之前需要了解一下Android中的消息機(jī)制。
方法1 Activity.runOnUiThread
方法如下:
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText("Hello");
}
});
這種方法簡(jiǎn)單易用,如果當(dāng)前線程是UI線程,那么行動(dòng)是立即執(zhí)行。如果當(dāng)前線程不是UI線程,就發(fā)布到事件隊(duì)列的UI線程。其實(shí)和Handler差不多,都是將這個(gè)更新UI的請(qǐng)求消息,加入到事件隊(duì)列,等待主線程空閑的時(shí)候執(zhí)行。
方法2 Handler
主線程中定義Handler如下:
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
String data = (String)msg.obj;
textView.setText(data);
break;
default:
break;
}
}
};
子線程發(fā)消息,通知Handler完成UI更新,代碼如下:
new Thread(new Runnable(){
@Override
public void run() {
//耗時(shí)操作
mHandler.sendEmptyMessage(0);
Message msg =new Message();
msg.obj = "數(shù)據(jù)";//可以是基本類(lèi)型,可以是對(duì)象,可以是List、map等
mHandler.sendMessage(msg);
}
}).start();
方法3 View.post
final Button btn =(Button)findViewById(R.id.btn);
btn.post(new Runnable(){
@Override
publicvoid run() {
btn.setText("Hello");
}
});
上面的代碼就是更新btn中的內(nèi)容,同樣下面的代碼也可以達(dá)到這種效果。
Handler handler = new Handler();
final Button btn = (Button)findViewById(R.id.btn);
handler.post(new Runnable(){
@Override
public void run() {
btn.setText("Hello");
}
});
這個(gè)是用handler.post方法,一個(gè)是用View.post方法,handler.post方法已經(jīng)在Android的消息機(jī)制中介紹過(guò)了,其實(shí)最終也是調(diào)用了方法2中的send方法。
現(xiàn)在看一下View.post方法的源代碼:
public boolean post(Runnable action) {
Handler handler;
AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
handler = attachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
return handler.post(action);
}
方法中主要的功能代碼就是attachInfo.mHandler,獲取當(dāng)前線程(即UI線程)的Hanlder,然后將action對(duì)象post到Handler里。在Handler里的處理過(guò)程上面鏈接文已經(jīng)分析的很清楚了,它將傳遞過(guò)來(lái)的action對(duì)象包裝成一個(gè)Message(Message的callback為action),然后將其投入U(xiǎn)I線程的消息循環(huán)中。在Handler的dispatchMessage方法里,第一句話就是為它所設(shè),直接調(diào)用runnable的run方法。而此時(shí),已經(jīng)路由到UI線程里,因此,我們可以毫無(wú)顧慮的來(lái)更新UI。
方法4 廣播
子線程中發(fā)送廣播,主線程中接收廣播并更新UI。
方法5 使用AsyncTask
為了簡(jiǎn)化子線程中訪問(wèn)UI,系統(tǒng)提供給了我們AsyncTask。
AsyncTask是一種輕量級(jí)的異步任務(wù)類(lèi),它可以在線程池中執(zhí)行后臺(tái)任務(wù),然后把執(zhí)行進(jìn)度和結(jié)果傳遞給主線程并更新UI。本質(zhì)上來(lái)說(shuō)AsyncTask封裝了Thread和Handler,但是AsyncTask不適合進(jìn)行特別耗時(shí)的后臺(tái)任務(wù),如果需要進(jìn)行特別耗時(shí)的任務(wù),建議使用線程池。
不同API版本的AsyncTask具有不同的表現(xiàn),因此需要注意。為了控制篇幅,具體的AsyncTask的使用方法和工作原理,我打算后面單獨(dú)成文進(jìn)行介紹。
以上所述是小編給大家介紹的Android開(kāi)發(fā)之子線程操作UI的幾種方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!
相關(guān)文章
Android學(xué)習(xí)筆記之藍(lán)牙功能
這篇文章主要為大家詳細(xì)介紹了Android學(xué)習(xí)筆記之藍(lán)牙功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09
簡(jiǎn)介Android應(yīng)用中sharedPreferences類(lèi)存儲(chǔ)數(shù)據(jù)的用法
這篇文章主要介紹了Android應(yīng)用中使用sharedPreferences類(lèi)存儲(chǔ)數(shù)據(jù)的方法,文中舉了用SharedPreferences保存數(shù)據(jù)和讀取數(shù)據(jù)的例子,需要的朋友可以參考下2016-02-02
Android實(shí)現(xiàn)dialog的3D翻轉(zhuǎn)示例
這篇文章主要介紹了Android實(shí)現(xiàn)dialog的3D翻轉(zhuǎn)示例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-08-08
手把手教你Android全局觸摸事件監(jiān)聽(tīng)
這篇文章主要介紹了Android全局觸摸事件監(jiān)聽(tīng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
Android 同時(shí)setTag兩次保存多種值的示例代碼
這篇文章主要介紹了Android 同時(shí)setTag兩次保存多種值的示例代碼,需要的朋友可以參考下2017-02-02
Android如何讓W(xué)ebView中的HTML5頁(yè)面實(shí)現(xiàn)視頻全屏播放
最近在工作遇到一個(gè)需求,需要讓W(xué)ebView中的HTML5頁(yè)面實(shí)現(xiàn)視頻全屏播放的效果,通過(guò)查找相關(guān)的資料終于找到了解決的方法,所以想著分享給大家,所以本文介紹了關(guān)于Android如何讓W(xué)ebView中的HTML5頁(yè)面實(shí)現(xiàn)視頻全屏播放的相關(guān)資料,需要的朋友可以參考學(xué)習(xí)。2017-04-04

