您的位置:首页 > 移动开发 > Android开发

android开发步步为营之40:AsyncTask的用法

2014-09-24 14:56 309 查看
一、理论

AsyncTask从字面上看的意思是异步的任务,就相当于html开发里面的ajax,能够异步的执行我们的任务。当然也就能一次性执行多个任务。

public abstract class

AsyncTask

extends Object

java.lang.Object



android.os.AsyncTask<Params, Progress, Result>

Class Overview

AsyncTask enables proper and easy use of the UI thread. This class allowsto perform background operations and publish results on the UI thread withouthaving to manipulate threads and/or handlers.

An asynchronous task is defined by a computation that runs on a backgroundthread and whose result is published on the UI thread. An asynchronous task isdefined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground,
onProgressUpdate and onPostExecute.

Developer Guides

For more information about using tasks and threads, read the Processesand Threads developer guide.

Usage

AsyncTask must be subclassed to be used. The subclass will override atleast one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)

Here is an example of subclassing:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {

protected Long doInBackground(URL... urls) {

int count = urls.length;

long totalSize = 0;

for (int i = 0; i < count; i++) {

totalSize += Downloader.downloadFile(urls[i]);

publishProgress((int) ((i / (float) count) * 100));

}

return totalSize;

}

protected void onProgressUpdate(Integer... progress) {

setProgressPercent(progress[0]);

}

protected void onPostExecute(Long result) {

showDialog("Downloaded" + result + " bytes");

}

}

Once created, a task is executed very simply:

new DownloadFilesTask().execute(url1, url2, url3);

AsyncTask's generic types

The three types used by an asynchronous task are the following:

$1__VE_ITEM__1. Params, the type of the parameters sent to the task upon execution.

$1__VE_ITEM__2. Progress, the type of the progress units published during the backgroundcomputation.

$1__VE_ITEM__3. Result, the type of the result of the background computation.

Not all types are always used by an asynchronous task. To mark a type asunused, simply use the type Void:

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

The 4 steps

When an asynchronous task is executed, the task goes through 4 steps:

$1__VE_ITEM__1. onPreExecute(), invoked on the UI thread immediately after the task isexecuted. This step is normally used to setup the task, for instance by showinga progress bar in the user interface.

$1__VE_ITEM__2. doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to performbackground computation that can take a long time. The parameters of theasynchronous task are passed
to this step. The result of the computation mustbe returned by this step and will be passed back to the last step. This stepcan also use publishProgress(Progress...) to publish one or more units of progress. These valuesare published on the UI thread, in the
onProgressUpdate(Progress...) step.

$1__VE_ITEM__3. onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This methodis used to display any form of progress in the user interface while thebackground
computation is still executing. For instance, it can be used toanimate a progress bar or show logs in a text field.

$1__VE_ITEM__4. onPostExecute(Result), invoked on the UI thread after the backgroundcomputation finishes. The result of the background computation is passed tothis step as a parameter.

二、实践

这里,我们实现这样一种功能:页面上点击开始我们的任务之后,执行两个任务:一个是将我们的盛大切客www.qieke.com的客户端下载到用户的手机上,另外一个任务就是抓取盛大在线www.sdo.com首页的内容。

开始我们的范例:

第一步:创建页面res/layout/asynctask.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<EditText android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/txtUrl1" android:layout_above="@+id/textView1" android:layout_marginBottom="22dp" android:layout_alignParentRight="true"android:layout_alignParentLeft="true">

<requestFocus></requestFocus>

</EditText>

<EditText android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/txtUrl2" android:layout_below="@+id/txtUrl1" android:layout_alignParentLeft="true"android:layout_marginTop="20dp"android:layout_alignParentRight="true"></EditText>

<Button android:text="开始我们的任务 " android:layout_width="wrap_content" android:id="@+id/btnOpen"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_toRightOf="@+id/tvContent2"android:layout_marginBottom="146dp"></Button>

<TextView android:id="@+id/tvContent1" android:layout_width="wrap_content" android:text="TextView" android:layout_height="wrap_content"android:layout_alignBaseline="@+id/tvContent2"android:layout_alignBottom="@+id/tvContent2"android:layout_toRightOf="@+id/btnOpen"android:layout_marginLeft="57dp"></TextView>

<TextView android:id="@+id/tvContent2" android:layout_width="wrap_content" android:text="TextView" android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"></TextView>

</RelativeLayout>

第二步:创建AsyncTastActivity.java

/**

*

*/

package com.figo.test;

importjava.io.ByteArrayOutputStream;

import java.io.File;

importjava.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.URL;

import java.net.URLConnection;

importorg.apache.http.HttpEntity;

importorg.apache.http.HttpResponse;

importorg.apache.http.client.HttpClient;

importorg.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;

importandroid.app.ProgressDialog;

import android.content.Context;

importandroid.content.DialogInterface;

import android.net.Uri;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Environment;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

/**

* @author Administrator

*

*/

public class AsyncTastActivityextends Activity {

private TextView message1;

private TextView message2;

private Button open;

private EditText url1;

private EditText url2;

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

setContentView(R.layout.asynctask);

message1= (TextView)findViewById(R.id.tvContent1);

message2= (TextView)findViewById(R.id.tvContent2);

url1= (EditText)findViewById(R.id.txtUrl1);

//盛大切客android客户端下载地址

url1.setText("http://p1.uvanimg.com/uploads/android/soft/Qieke_android_qieke211_c_20111014_V$2.apk");

url2= (EditText)findViewById(R.id.txtUrl2);

//盛大在线地址

url2.setText("http://www.sdo.com");

open= (Button)findViewById(R.id.btnOpen);

open.setOnClickListener(new View.OnClickListener() {

public voidonClick(View arg0) {

connect();

}

});

}

private void connect() {

DownloadTask task1 = new DownloadTask(this);

task1.execute(url1.getText().toString());

GrabTask task2 = new GrabTask(this);

task2.execute(url2.getText().toString());

}

//下载任务

class DownloadTask extendsAsyncTask<String, Integer, String> {

ProgressDialog pdialog;

Context contextnew;

public DownloadTask(Context context){

contextnew=context;

pdialog = newProgressDialog(context, 0);

pdialog.setButton("cancel",new DialogInterface.OnClickListener() {

public voidonClick(DialogInterface dialog, int i) {

dialog.cancel();

}

});

pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {

public voidonCancel(DialogInterface dialog) {

finish();

}

});

pdialog.setTitle("当前下载进度");

pdialog.setCancelable(true);

pdialog.setMax(100);

pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

pdialog.show();

}

@Override

protected StringdoInBackground(String... params) {

try{

downloadApkFromURL(params[0]);

} catch(Exceptione) {

e.printStackTrace();

}

return "下载完成";

}

@Override

protected voidonCancelled() {

super.onCancelled();

}

@Override

protected voidonPostExecute(String result) {

// 下载完成提示,同时关闭进度条

message1.setText(result);

pdialog.dismiss();

}

@Override

protected voidonPreExecute() {

// 任务启动,可以在这里显示一个对话框,这里简单处理

message1.setText(R.string.taskstarted);

}

@Override

protected voidonProgressUpdate(Integer... values) {

// 更新进度

System.out.println(""+values[0]);

message1.setText(""+values[0]);

pdialog.setProgress(values[0]);

}

private UridownloadApkFromURL(String url) {

try {

URLConnectionconnection = (new URL(url)).openConnection();

if (connection!= null) {

intcontentLength = connection.getContentLength();

int len,length = 0;

byte[] buf= new byte[1024];

InputStreamis = connection.getInputStream();

File file =new File(contextnew.getCacheDir(), "qieke");//放入内存

//File file= new File(Environment.getExternalStorageDirectory() , "qieke");//放入sd卡

if(!file.exists()) {

file.createNewFile();

}

Runtime.getRuntime().exec("chmod 777 " +file.getAbsolutePath());

OutputStream os = new FileOutputStream(file);

try {

while((len = is.read(buf, 0, buf.length)) > 0) {

os.write(buf, 0, len);

length += len;

publishProgress((int) (100 * (float) length / contentLength));

}

os.flush();

} finally {

is.close();

os.close();

}

returnUri.fromFile(file);

}

} catch(IOException ioe) {

Log.e("downloading latest apk",ioe.getMessage()+"-->" + url) ;

}

return null;

}

}

//抓取页面任务

class GrabTask extendsAsyncTask<String, Integer, String> {

ProgressDialog pdialog;

public GrabTask(Context context){

pdialog = newProgressDialog(context, 0);

pdialog.setButton("cancel", newDialogInterface.OnClickListener() {

public voidonClick(DialogInterface dialog, int i) {

dialog.cancel();

}

});

pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {

public voidonCancel(DialogInterface dialog) {

finish();

}

});

pdialog.setTitle("当前抓取进度");

pdialog.setCancelable(true);

pdialog.setMax(100);

pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

pdialog.show();

}

@Override

protected StringdoInBackground(String... params) {

try{

HttpClientclient = new DefaultHttpClient();

// params[0]代表连接的url

HttpGet get =new HttpGet(params[0]);

HttpResponseresponse = client.execute(get);

HttpEntityentity = response.getEntity();

long length =entity.getContentLength();

InputStream is =entity.getContent();

String s = null;

if(is != null) {

ByteArrayOutputStream baos = new ByteArrayOutputStream();

byte[] buf = new byte[128];

int ch = -1;

int count =0;

while((ch =is.read(buf)) != -1) {

baos.write(buf, 0, ch);

count +=ch;

if(length> 0) {

// 如果知道响应的长度,调用publishProgress()更新进度

publishProgress((int) ((count / (float) length) * 100));

}

// 让线程休眠100ms

Thread.sleep(100);

}

s = newString(baos.toByteArray()); }

// 返回结果

return s;

} catch(Exceptione) {

e.printStackTrace();

}

return null;

}

@Override

protected void onCancelled(){

super.onCancelled();

}

@Override

protected voidonPostExecute(String result) {

// 返回HTML页面的内容

message2.setText(result);

pdialog.dismiss();

}

@Override

protected voidonPreExecute() {

// 任务启动,可以在这里显示一个对话框,这里简单处理

message2.setText(R.string.taskstarted);

}

@Override

protected voidonProgressUpdate(Integer... values) {

// 更新进度

System.out.println(""+values[0]);

message2.setText(""+values[0]);

pdialog.setProgress(values[0]);

}

}

}

第三步、AndroidManifest.xml加入我们的Activity

<activity android:name="com.figo.test.AsyncTastActivity" android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

提示一点我们这两个个任务需要访问的权限,所以需要加入:

<uses-permissionandroid:name="android.permission.INTERNET"/>

第四步:运行效果

可以看到两个任务都在运行

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: