多线程异步处理:AsyncTask异步更新UI界面(详细完整总结篇)
為什么80%的碼農都做不了架構師?>>>
轉載自:http://blog.csdn.net/mylzc/article/details/6772129?,在原先的基礎上整理項目并重新發布。
AsyncTask的內部實現是一個線程池,每個后臺任務會提交到線程池中的線程執行,然后使用Thread+Handler的方式調用回調函數。
AsyncTask抽象出后臺線程運行的五個狀態,分別是:1、準備運行,2、正在后臺運行,3、進度更新,4、完成后臺任務,5、取消任務,對于這五個階段,AsyncTask提供了五個回調方法:
1、準備運行:onPreExecute(),該回調方法在任務被執行之后立即由UI線程調用。這個步驟通常用來建立任務,在UI上顯示進度條。
2、正在后臺運行:doInBackground(Params...),該回調方法由后臺線程在onPreExecute()方法執行結束后立即調用。通常在這里執行耗時的后臺計算,計算的結果必須由該方法返回,并被傳遞到onPostExecute()中。在該方法內也可使用publishProgress(Progress...)來發布一個或多個進度單位(units of progress),這些值將會在onProgressUpdate(Progress...)中被發布到UI線程。
3. 進度更新:onProgressUpdate(Progress...),該方法由UI線程在publishProgress(Progress...)方法調用完后被調用,一般用于動態地顯示一個進度條。
4. 完成后臺任務:onPostExecute(Result),當后臺計算結束后調用。后臺計算的結果會被作為參數傳遞給該方法。
5、取消任務:onCancelled (),在調用AsyncTask的cancel()方法時調用
?
AsyncTask的構造函數有三個模板參數:
1.Params:傳遞給后臺任務的參數類型。
2.Progress:后臺計算執行過程中,進步單位(progress units)的類型(就是后臺程序已經執行了百分之幾了)。
3.Result:后臺執行返回的結果的類型。
AsyncTask并不總是需要使用上面的全部3種類型。標識不使用的類型很簡單,只須用Void類型即可。
?
項目分析:
1、獲取網絡圖片
點擊按鈕,模擬一個耗時動作,從網站下載圖片并顯示,取消按鈕模擬取消操作,將進度條的值置零,并且換背景圖片。
?
完整代碼:
package com.xsjayz.at;import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient;import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast;/*** AsyncTask* * @version 2012-09-02*/ public class AsyncTaskActivity extends Activity {private final static String IMAGE_PATH = "http://www.oschina.net/img/logo.gif";private ImageView imageView;private Button button;private Button button2;private ProgressBar progressBar;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);imageView = (ImageView) findViewById(R.id.imageView);button = (Button) findViewById(R.id.button);button2 = (Button) findViewById(R.id.button2);progressBar = (ProgressBar) findViewById(R.id.progressBar);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {MyTask myTask = new MyTask();myTask.execute(IMAGE_PATH);}});button2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {MyTask myTask = new MyTask();myTask.cancel(true);}});}/*** 繼承AsyncTask*/class MyTask extends AsyncTask<String, Integer, Bitmap> {/*** 準備運行*/// 該回調方法在任務被執行之后立即由UI線程調用。這個步驟通常用來建立任務,在UI上顯示進度條。@Overrideprotected void onPreExecute() {imageView.setImageBitmap(null);// 每次在準備階段先清除掉設置的圖片progressBar.setProgress(0);// 進度條初始值0}/*** 正在后臺運行*/// 該回調方法由后臺線程在onPreExecute()方法執行結束后立即調用。// 通常在這里執行耗時的后臺計算,計算的結果必須由該函數返回,并被傳遞到onPostExecute()中。// 在該方法內也可使用publishProgress()來發布一個或多個進度單位,這些值將會在onProgressUpdate()中被發布到UI線程。@Overrideprotected Bitmap doInBackground(String... params) {// 發布進度單位,系統將會調用onProgressUpdate()方法更新這些值。publishProgress(0);// 進度值0final Bitmap bitmap;HttpClient httpClient = new DefaultHttpClient();// 獲取網站圖片HttpGet httpGet = new HttpGet(params[0]);publishProgress(30);// 進度值30try {HttpResponse httpResponse = httpClient.execute(httpGet);publishProgress(70);// 進度值70bitmap = BitmapFactory.decodeStream(httpResponse.getEntity().getContent());} catch (Exception e) {return null;}publishProgress(100);// 進度值100return bitmap;}/*** 進度更新*/// 該方法由UI線程在publishProgress()方法調用完后被調用,一般用于動態地顯示一個進度條。protected void onProgressUpdate(Integer... progress) {// 更新進度條的進度progressBar.setProgress(progress[0]);}/*** 完成后臺任務*/// 后臺任務執行完之后被調用,在UI線程執行。protected void onPostExecute(Bitmap result) {if (result != null) {Toast.makeText(AsyncTaskActivity.this, "獲取圖片成功",Toast.LENGTH_LONG).show();imageView.setImageBitmap(result);} else {Toast.makeText(AsyncTaskActivity.this, "獲取圖片失敗",Toast.LENGTH_LONG).show();}}/*** 取消任務*/// 在調用AsyncTask的cancel()方法時調用,在UI線程執行。@Overrideprotected void onCancelled() {progressBar.setProgress(0);// 進度條復位imageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));Toast.makeText(AsyncTaskActivity.this, "取消從網絡獲取的圖片",Toast.LENGTH_LONG).show();}} }
布局文件:main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><ProgressBarandroid:id="@+id/progressBar"style="?android:attr/progressBarStyleHorizontal"android:layout_width="fill_parent"android:layout_height="wrap_content" ></ProgressBar><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:orientation="horizontal" ><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/download_btn" /><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/cancel_btn" /></LinearLayout><ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content" /></LinearLayout>總結:
AsyncTask抽象出一個后臺任務的五種狀態,對應了五個回調接口,我們只需要根據不同的需求實現這五個接口(doInBackground是必須要實現的),就能完成一些簡單的后臺任務。
流程說明:
1、 ?點擊按鈕時,創建一個MyTask,并且傳入圖片地址(String類型參數,因此AsyncTask的第一個模板參數為String類型)。
2、? UI線程執行onPreExecute(),把ImageView的圖片清空,progrssbar的進度清零。
3、? 后臺線程執行doInBackground(),不可以在doInBackground()操作UI,調用publishProgress(0)更新進度,此時會調用onProgressUpdate()更新進度條(進度用整形表示,因此AsyncTask的第二個模板參數是Integer)。方法最后返回result(例中返回Bitmap類型,因此AsyncTask的第二個模板參數是Bitmap)。
4、? 當后臺任務執行完成后,調用onPostExecute(Result),傳入的參數是doInBackground()中返回的對象。
轉載于:https://my.oschina.net/xsjayz/blog/76105
總結
以上是生活随笔為你收集整理的多线程异步处理:AsyncTask异步更新UI界面(详细完整总结篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++关键字(1)——const
- 下一篇: [转]ActiveX控件安全初始化之一: