❶ android子線程更新UI的方法
在進行Android開發時,需確保UI操作僅在主線程中執行,以避免應用性能問題。若需在子線程中更新UI,可採取以下策略:
一種常用方法是使用Handler。在主線程定義Handler實例,利用其發送消息與回調機制,在子線程執行完畢後更新UI。
另一種選擇是AsyncTask,一個輕量級的非同步任務類。它在子線程中執行後台任務,通過回調方法如doInBackground、onProgressUpdate和onPostExecute傳遞結果至主線程,進而更新UI。
還有一種方法是Activity的runOnUiThread方法。通過Activity對象調用此方法,可將更新UI的代碼放入回調中執行。
最後,可利用View.post(Runnable r)方法,將更新UI的Runnable對象傳遞給視圖,由視圖在合適時機執行該操作。
盡管以上方法允許子線程更新UI,頻繁操作仍可能對應用性能造成負面影響。因此,應謹慎使用。
❷ 如何在子線程中更新ui
在子線程中更新UI:由於安卓更新UI元素必須在主線程中,否則就會出現異常。有時候我們必須在子線程里去執行一些耗時任務,然後根據任務的執行結果來更新相應的UI控制項,比如:執行網路請求,需要將傳回的數據更新到UI上。
操作方法:
一、在主線程中new出Handler的實例handler,在Handler的handleMessage()方法中傳回的Message對象屬性進行判斷,當滿足要求時,執行UI更新的操作。
在子線程的run()方法內,1、實例化Message對象message;2、對象調用Message的what變數,設置message的屬性;3、對象調用sendMessage()方法,將Message對象發送出去。
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
// 在這里可以進行UI操作
text.setText("Nice to meet you");
break;
default:
break;
}
}
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message); // 將Message對象發送出去
}
}).start();
❸ android通過Handler使子線程更新UI
在Android項目中經常有碰到這樣的問題,在子線程中完成耗時操作之後要更新UI,下面就自己經歷的一些項目總結一下更新的方法。
一. 引言
首先來看一下android中消息機制:
專業術語:
Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。
MessageQueue:消息隊列,用來存放Handler發送過來的消息,並按照FIFO規則執行。當然,存放Message並非實際意義的保存,而是將Message以鏈表的方式串聯起來的,等待Looper的抽取。
Looper:消息泵,不斷地從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。
Thread:線程,負責調度整個消息循環,即消息循環的執行場所。
二. 方法
1. 用Handler
(1)主線程中定義Handler:
java代碼:
[java]view plain
HandlermHandler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
super.handleMessage(msg);
switch(msg.what){
case0:
<spanstyle="color:#009900;">//完成主界面更新,拿到數據</span>
Stringdata=(String)msg.obj;
updateWeather();
textView.setText(data);
break;
default:
break;
}
}
};
(2)子線程發消息,通知Handler完成UI更新:
java代碼:
privatevoipdateWeather(){
newThread(newRunnable(){
@Override
publicvoidrun(){
<spanstyle="color:#009900;">//耗時操作,完成之後發送消息給Handler,完成UI更新;</span>
mHandler.sendEmptyMessage(0);
<spanstyle="color:#33cc00;">//需要數據傳遞,用下面方法;</span>
Messagemsg=newMessage();
msg.obj="數據";<spanstyle="color:#33cc00;">//可以是基本類型,可以是對象,可以是List、map等;</span>
mHandler.sendMessage(msg);
}
}).start();
}
注意:Handler對象必須定義在主線程中,如果是多個類直接互相調用,就不是很方便,需要傳遞content對象或通過介面調用。
2.用Activity對象的runOnUiThread方法更新
在子線程中通過runOnUiThread()方法更新UI:
java代碼:
newThread(){
publicvoidrun(){
<spanstyle="color:#009900;">//這兒是耗時操作,完成之後更新UI;</span>
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
<spanstyle="color:#009900;">//更新UI</span>
imageView.setImageBitmap(bitmap);
}
});
}
}.start();
如果在非上下文類中,可以通過傳遞上下文實現調用:
java代碼:
Activityactivity=(Activity)imageView.getContext();
activity.runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
imageView.setImageBitmap(bitmap);
}
});
注意:這種方法使用比較靈活,但如果Thread定義在其他地方,需要傳遞Activity對象。
3.
View.post(Runnable r)
java代碼:
imageView.post(newRunnable(){
@Override
publicvoidrun(){
imageView.setImageBitmap(bitmap);
}
});
這種方法更簡單,但需要傳遞要更新的View過去。
總結:UI的更新必須在主線程中完成,所以不管上述那種方法,都是將更新UI的消息發送到了主線程的消息對象,讓主線程做處理。
❹ 在多線程中,子線程更新主線程ui有哪些方法及注意點
Android
UI多線程Androidthread工作
在一個Android 程序開始運行的時候,會單獨啟動一個Process。默認的情況下,所有這個程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的兩種,除此之外還有Content Provider和Broadcast Receiver)都會跑在這個Process。
一個Android 程序默認情況下也只有一個Process,但一個Process下卻可以有許多個Thread。在這么多Thread當中,有一個Thread,我們稱之為UI Thread。UI Thread在Android程序運行的時候就被創建,是一個Process當中的主線程Main Thread,主要是負責控制UI界面的顯示、更新和控制項交互。在Android程序創建之初,一個Process呈現的是單線程模型,所有的任務都在一個線程中運行。因此,我們認為,UI Thread所執行的每一個函數,所花費的時間都應該是越短越好。而其他比較費時的工作(訪問網路,下載數據,查詢資料庫等),都應該交由子線程去執行,以免阻塞主線程。
那麼,UI Thread如何和其他Thread一起工作呢?常用方法是:
誕生一個主線程的Handler物件,當做Listener去讓子線程能將訊息Push到主線程的Message Quene里,以便觸發主線程的handlerMessage()函數,讓主線程知道子線程的狀態,並在主線程更新UI。
例如,在子線程的狀態發生變化時,我們需要更新UI。如果在子線程中直接更新UI,通常會拋出下面的異常:11-07 13:33:04.393: ERROR/JavaBinder(1029):android.view.ViewRoot$:Only the original thread that created a view hierarchy can touch its views.
意思是,無法在子線程中更新UI。為此,我們需要通過Handler物件,通知主線程Ui Thread來更新界面。
如下,首先創建一個Handler,來監聽Message的事件:
private final int UPDATE_UI = 1;private Handler mHandler = new MainHandler();private class MainHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case UPDATE_UI: {Log.i("TTSDeamon", "UPDATE_UI");showTextView.setText(editText.getText().toString());ShowAnimation();break;}default:break;}}}
或者
private Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case UPDATE_UI: {Log.i("TTSDeamon", "UPDATE_UI");showTextView.setText(editText.getText().toString());ShowAnimation();break;}default:break;}}}
當子線程的狀態發生變化,則在子線程中發出Message,通知更新UI。
mHandler.sendEmptyMessageDelayed(UPDATE_UI, 0);
在我們的程序中,很多Callback方法有時候並不是運行在主線程當中的,所以如果在Callback方法中更新UI失敗,也可以採用上面的方法。