androidhandler更新ui
⑴ Android子線程中更新UI【方法+演練】
在Android開發中,子線程更新UI是一個常見的需求。本文將介紹幾種方法來實現這一功能,並通過具體示例進行演練。
方法一:利用Handler。在主線程中定義Handler,子線程通過發送消息給Handler完成UI更新。這種方法適用於多個類間的直接調用,但當需要傳遞復雜數據時,可能不夠靈活。
方法二:使用Activity對象的runOnUiThread方法更新UI。這種方法在子線程中通過調用runOnUiThread()方法執行UI更新,操作相對靈活,但需要確保方法調用時的上下文為Activity。
方法三:使用View.post(Runnable r)。這是一種簡單的方法,將要執行的Runnable包裝在post方法中,以便在主線程中執行。此方法要求傳遞要更新的View對象。
方法四:利用AsyncTask。這是一個官方推薦的解決方案,它提供了一種簡潔的方式來在子線程中執行耗時操作並在UI線程中更新UI。AsyncTask是一個抽象類,需要創建子類並重寫三個抽象方法:doInBackground、onProgressUpdate和onPostExecute。
演練過程:在Android中,線程主要分為UI線程(主線程)和其他子線程。主線程不適合執行耗時操作,因此子線程用於處理這些操作。在子線程中進行耗時操作後,需要通過特定的API將結果返回給主線程,以更新UI。以下是一個示例,展示了如何在子線程中執行下載任務並在主線程中更新UI。
點擊按鈕後,子線程啟動模擬下載操作,1秒後完成任務並返回數據。使用數據更新UI。通過以下六種方法,可以實現這個功能:
1. 使用Activity.runOnUiThread()方法。此方法適用於當前對象為Activity的情況。通過傳遞一個Runnable對象,可以在UI線程中執行更新操作。
2. 使用View.post()方法。同樣適用於View對象,通過傳遞Runnable介面執行更新。
3. 使用View.postDelayed()方法。此方法允許在指定延遲後執行UI更新,參數為延遲時間和Runnable介面。
4. 使用Handler.post()方法。創建一個Handler對象,然後使用post方法在UI線程中執行更新。
5. 引用AsyncTask。這是一個官方推薦的方法,它提供了一個更高級的框架來處理非同步任務,包括UI更新。
6. 了解Handler機制的核心作用。無論是上述哪種方法,其背後的機制都是Handler,它負責將子線程中的UI更新消息傳遞到UI線程進行處理。
為了更深入地理解Android開發中的核心概念,建議閱讀《Android核心技術手冊》,它涵蓋了大量小知識點和30多個模塊,是進階學習的寶貴資源。
更新*UI,指的是改變頁面效果,即用戶在界面上可見的變化。線程是程序運行時內部的執行流,主線程是在程序啟動時創建的並運行的初始線程,而子線程則是從主線程衍生出來的。這些概念和方法是Android開發中不可或缺的基礎知識。
⑵ 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的消息發送到了主線程的消息對象,讓主線程做處理。
⑶ Android:在一個非主線程內直接調用UI線程的Handler實例,這樣沒問題嗎
在Android開發中,我們常常遇到線程安全的問題,特別是在子線程和UI線程之間進行交互時。為了保證應用程序的穩定性和用戶體驗,我們不能直接在子線程中更新UI線程中的UI元素。為了解決這個問題,Android提供了一種機制——Handler。
Handler的工作原理是這樣的:當子線程需要更新UI線程中的UI元素時,它會通過發送消息的方式,將需要更新的內容傳遞給UI線程。這些消息會被放入UI線程的消息隊列中,然後由UI線程中的Handler逐個處理。這樣,我們就可以在子線程中執行耗時操作,同時在UI線程中更新UI,從而保證了界面的流暢性。
在Android中,創建多線程的方式主要有兩種:一種是通過繼承Thread類並重寫run方法;另一種是通過實現Runnable介面並實現run方法。無論哪種方式,子線程都無法直接修改UI線程中的UI元素,而Handler正是用來解決這一問題的關鍵。
Handler的主要方法包括post、postAtTime、postDelayed、sendEmptyMessage、sendMessage、sendMessageAtTime、sendMessageDelayed等。這些方法分別用於在主線程中執行Runnable或發送消息。通過這些方法,我們可以靈活地控制消息的發送時機和執行方式。
下面,我們通過一個簡單的例子來說明Handler的使用方法。假設我們需要在主線程中的TextView中顯示10到100之間的隨機數,每隔5秒更新一次,總共更新5次。主要代碼如下:
java
int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler.post(run);
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
String s = String.valueOf(msg.what);
TextView tv = (TextView)findViewById(R.id.textView);
tv.setText(tv.getText() + " " + s);
}
};
Runnable run = new Runnable(){
@Override
public void run(){
Random r = new Random();
int rnum = r.nextInt((100 - 10) + 1) + 10;
handler.sendEmptyMessage(rnum);
handler.postDelayed(run, 5000);
i++;
if (i==5){
handler.removeCallbacks(run);
}
}
};
通過這個例子,我們可以看到Handler在處理子線程與UI線程之間的交互時的重要作用。在實際開發中,我們可以根據具體需求,靈活地使用Handler的各種方法來實現復雜的線程交互邏輯。
⑷ android之Handler處理機制
在深入研究Handler之前,讓我們先思考幾個關鍵問題:
1. Handler的必要性
Android設計Handler機制的主要目的是解決多線程並發中的UI更新問題。設想在一個Activity中,多個線程試圖並行更新UI,如果沒有恰當處理,會導致界面混亂。而對所有UI操作強制加鎖會犧牲性能。
2. Handler的作用
為了解決上述問題,Android提供了一套機制,讓所有的UI更新都在主線程的消息隊列中非同步處理,無需開發者直接關心並發問題。Handler就是實現這一機制的關鍵。
3. Handler工作原理
Handler與通信的非同步同步概念相關。它就像一個非同步回調的執行者,子線程通過Handler向主線程發送消息,這些消息在MessageQueue中按順序等待,Looper負責取出並分發給對應的Handler處理。
4. 如何操作
創建Handler時,它與Looper綁定,通常是當前線程的Looper。在非主線程,需先開啟Looper並綁定到Handler,確保消息能正確傳遞。消息的發送、Looper的輪詢和Handler的回調構成了整個工作流程。
5. 關鍵類理解
包括Message、Handler和Looper,Message用於封裝任務數據,Handler負責處理消息,Looper則負責消息隊列的管理。創建Handler時,確保在主線程,否則需手動設置Looper。