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

一、理论
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"/>
 
第四步:运行效果
可以看到两个任务都在运行
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值