Android的UI更新只能在UI線程中,即主線程。子線程中若是要進行UI更新,都是要通知主線程來進行。ide
幾種實現方式總結以下,歡迎補充。函數
一、runOnUiThread()oop
子線程中持有當前Activity引用(假如爲Activity mActivity;),便可以調用mActivity的runOnUiThread(Runnable r)方法。post
二、post()和postDelay()this
子線程若是持有某個View的引用,要對該View進行更新,則可調用該View對象的post(Runnable r)或postDelay(Runnable r)方法url
Handler對象也有post()方法。其實在Android的源碼中,這些post()方法都是藉助下面的第3種方法:Handler + Message來實現的。spa
三、Handler + Message或者Handler + Thread + Message線程
主線程創建時,默認狀況下是有Looper的,能夠處理消息隊列。orm
在主線程創建一個Handler對象,複寫其handleMessage()方法,在該方法中實現UI更新。對象
示例:
private static final int MSG_CODE = 1001;
private Handler mHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
//接收並處理消息
if(msg.what == MSG_CODE)
{
//UI更新
}
}
};
public void doSomething()
{
new Thread()
{
@Override
public void run()
{
//子線程發送信息
Message msg = mHandler.obtainMessage(MSG_CODE);
msg.sendToTarget();
}
}.start();
}
四、Broadcast
子線程中發送廣播,主線程中接收廣播並更新UI
五、AsyncTask
AsyncTask可方便地實現新開一個線程,並將結果返回給UI線程,而不須要開發者手動去新開一個線程,也無須開發者使用Handler,很是方便。
應當注意的是AsyncTask是一個抽象類,其三個泛型參數的意義以下:
AsyncTask<Param, Progress, Result>
Param:發送給新開的線程的參數類型
Progress:表徵任務處理進度的類型。
Result:線程任務處理完以後,返回給UI線程的值的類型。
該類中有四個抽象函數,onPreExecute(), doInBackground(Params... param),
onProgressUpdate(Progress... progress), onPostExecute(Result result)。
除了,doInBackground(Params...)方法,其它三個方法都運行在UI線程。
自定義一個類繼承AsyncTask並至少實現 doInBackground()函數。在該函數中執行的過程當中,能夠隨時調用publishProgress(Progress...)報告其執行進 度。此時會觸發另外一個方法onProgressUpdate(Progress... progress),以便在UI線程中的某些控件(如ProgressBar)上更新任務處理的進度。
也能夠等doInBackground()執行完,進入onPostExecute()方法後,再進行UI控件的更新。
可在任意時間,任意線程中,取消AsyncTask開啓的任務(調用自定義的AsynTask子類的cancel(boolean mayInterruptIfRunning)方法)
使用示例以下:
//若是沒記錯的話,這個例子應該是以前總結的時候從官網剪下來的
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}