多线程异步处理:AsyncTask异步更新UI界面(详细完整总结篇)
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>>
轉(zhuǎn)載自:http://blog.csdn.net/mylzc/article/details/6772129?,在原先的基礎(chǔ)上整理項(xiàng)目并重新發(fā)布。
AsyncTask的內(nèi)部實(shí)現(xiàn)是一個線程池,每個后臺任務(wù)會提交到線程池中的線程執(zhí)行,然后使用Thread+Handler的方式調(diào)用回調(diào)函數(shù)。
AsyncTask抽象出后臺線程運(yùn)行的五個狀態(tài),分別是:1、準(zhǔn)備運(yùn)行,2、正在后臺運(yùn)行,3、進(jìn)度更新,4、完成后臺任務(wù),5、取消任務(wù),對于這五個階段,AsyncTask提供了五個回調(diào)方法:
1、準(zhǔn)備運(yùn)行:onPreExecute(),該回調(diào)方法在任務(wù)被執(zhí)行之后立即由UI線程調(diào)用。這個步驟通常用來建立任務(wù),在UI上顯示進(jìn)度條。
2、正在后臺運(yùn)行:doInBackground(Params...),該回調(diào)方法由后臺線程在onPreExecute()方法執(zhí)行結(jié)束后立即調(diào)用。通常在這里執(zhí)行耗時的后臺計算,計算的結(jié)果必須由該方法返回,并被傳遞到onPostExecute()中。在該方法內(nèi)也可使用publishProgress(Progress...)來發(fā)布一個或多個進(jìn)度單位(units of progress),這些值將會在onProgressUpdate(Progress...)中被發(fā)布到UI線程。
3. 進(jìn)度更新:onProgressUpdate(Progress...),該方法由UI線程在publishProgress(Progress...)方法調(diào)用完后被調(diào)用,一般用于動態(tài)地顯示一個進(jìn)度條。
4. 完成后臺任務(wù):onPostExecute(Result),當(dāng)后臺計算結(jié)束后調(diào)用。后臺計算的結(jié)果會被作為參數(shù)傳遞給該方法。
5、取消任務(wù):onCancelled (),在調(diào)用AsyncTask的cancel()方法時調(diào)用
?
AsyncTask的構(gòu)造函數(shù)有三個模板參數(shù):
1.Params:傳遞給后臺任務(wù)的參數(shù)類型。
2.Progress:后臺計算執(zhí)行過程中,進(jìn)步單位(progress units)的類型(就是后臺程序已經(jīng)執(zhí)行了百分之幾了)。
3.Result:后臺執(zhí)行返回的結(jié)果的類型。
AsyncTask并不總是需要使用上面的全部3種類型。標(biāo)識不使用的類型很簡單,只須用Void類型即可。
?
項(xiàng)目分析:
1、獲取網(wǎng)絡(luò)圖片
點(diǎn)擊按鈕,模擬一個耗時動作,從網(wǎng)站下載圖片并顯示,取消按鈕模擬取消操作,將進(jìn)度條的值置零,并且換背景圖片。
?
完整代碼:
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> {/*** 準(zhǔn)備運(yùn)行*/// 該回調(diào)方法在任務(wù)被執(zhí)行之后立即由UI線程調(diào)用。這個步驟通常用來建立任務(wù),在UI上顯示進(jìn)度條。@Overrideprotected void onPreExecute() {imageView.setImageBitmap(null);// 每次在準(zhǔn)備階段先清除掉設(shè)置的圖片progressBar.setProgress(0);// 進(jìn)度條初始值0}/*** 正在后臺運(yùn)行*/// 該回調(diào)方法由后臺線程在onPreExecute()方法執(zhí)行結(jié)束后立即調(diào)用。// 通常在這里執(zhí)行耗時的后臺計算,計算的結(jié)果必須由該函數(shù)返回,并被傳遞到onPostExecute()中。// 在該方法內(nèi)也可使用publishProgress()來發(fā)布一個或多個進(jìn)度單位,這些值將會在onProgressUpdate()中被發(fā)布到UI線程。@Overrideprotected Bitmap doInBackground(String... params) {// 發(fā)布進(jìn)度單位,系統(tǒng)將會調(diào)用onProgressUpdate()方法更新這些值。publishProgress(0);// 進(jìn)度值0final Bitmap bitmap;HttpClient httpClient = new DefaultHttpClient();// 獲取網(wǎng)站圖片HttpGet httpGet = new HttpGet(params[0]);publishProgress(30);// 進(jìn)度值30try {HttpResponse httpResponse = httpClient.execute(httpGet);publishProgress(70);// 進(jìn)度值70bitmap = BitmapFactory.decodeStream(httpResponse.getEntity().getContent());} catch (Exception e) {return null;}publishProgress(100);// 進(jìn)度值100return bitmap;}/*** 進(jìn)度更新*/// 該方法由UI線程在publishProgress()方法調(diào)用完后被調(diào)用,一般用于動態(tài)地顯示一個進(jìn)度條。protected void onProgressUpdate(Integer... progress) {// 更新進(jìn)度條的進(jìn)度progressBar.setProgress(progress[0]);}/*** 完成后臺任務(wù)*/// 后臺任務(wù)執(zhí)行完之后被調(diào)用,在UI線程執(zhí)行。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();}}/*** 取消任務(wù)*/// 在調(diào)用AsyncTask的cancel()方法時調(diào)用,在UI線程執(zhí)行。@Overrideprotected void onCancelled() {progressBar.setProgress(0);// 進(jìn)度條復(fù)位imageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));Toast.makeText(AsyncTaskActivity.this, "取消從網(wǎng)絡(luò)獲取的圖片",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>總結(jié):
AsyncTask抽象出一個后臺任務(wù)的五種狀態(tài),對應(yīng)了五個回調(diào)接口,我們只需要根據(jù)不同的需求實(shí)現(xiàn)這五個接口(doInBackground是必須要實(shí)現(xiàn)的),就能完成一些簡單的后臺任務(wù)。
流程說明:
1、 ?點(diǎn)擊按鈕時,創(chuàng)建一個MyTask,并且傳入圖片地址(String類型參數(shù),因此AsyncTask的第一個模板參數(shù)為String類型)。
2、? UI線程執(zhí)行onPreExecute(),把ImageView的圖片清空,progrssbar的進(jìn)度清零。
3、? 后臺線程執(zhí)行doInBackground(),不可以在doInBackground()操作UI,調(diào)用publishProgress(0)更新進(jìn)度,此時會調(diào)用onProgressUpdate()更新進(jìn)度條(進(jìn)度用整形表示,因此AsyncTask的第二個模板參數(shù)是Integer)。方法最后返回result(例中返回Bitmap類型,因此AsyncTask的第二個模板參數(shù)是Bitmap)。
4、? 當(dāng)后臺任務(wù)執(zhí)行完成后,調(diào)用onPostExecute(Result),傳入的參數(shù)是doInBackground()中返回的對象。
轉(zhuǎn)載于:https://my.oschina.net/xsjayz/blog/76105
總結(jié)
以上是生活随笔為你收集整理的多线程异步处理:AsyncTask异步更新UI界面(详细完整总结篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++关键字(1)——const
- 下一篇: [转]ActiveX控件安全初始化之一: