zoukankan      html  css  js  c++  java
  • Android--多线程之AsyncTask

    前言

      本片博客将介绍AsyncTask的使用,之前有介绍过线程和进程。而在AsyncTask中,运行在用户界面中,执行异步操作,并且把执行结果发布在UI线程上,且也不需要处理线程和Handler。在本篇博客里,将会讲解到AsyncTask的基本介绍,以及如何使用,最后会以一个简单的Demo讲解AsyncTask的使用。

    AsyncTask

      AsyncTask,异步任务,可以简单进行异步操作,并把执行结果发布到UI主线程。AsyncTask是一个抽象类,它的内部其实也是结合了Thread和Handler来实现异步线程操作,但是它形成了一个通用线程框架,更清晰简单。AsyncTask应该被用于比较简短的操作(最多几秒钟)。如果需要保持长时间运行的线程,可以使用ThreadPooExecutor或者FutureTask,关于这两个类的内容,以后再介绍,本片博客主要介绍AsyncTask。

      AsyncTask被定义为一个操作,运行在一个后台线程中,其结果被发布在UI线程上。它的异步工作的参数与返回值被泛型的三个参数指定:Params、Progress、Result。AsyncTask将经历4个步骤:onPreExecute、doInBackground、onProgressUpdate、onPostExecute。下面详细讲解这三个参数与四个步骤:

      三个泛型参数:

    • Params:被发送到执行任务的参数类型。
    • Progress:进度的类型,发送后台的计算进度到UI线程类型。
    • Result:异步任务的返回结果类型。

      一个异步任务将经历四个阶段:

    • onPreExecute():执行在UI线程上调用执行任务之前,一般用于设置任务。
    • doInBackground(Params...):主要是用来执行异步任务的耗时操作,可以在这个方法中通过publishProgress()方法发布进度信息,并在执行完成之后,返回执行结果。
    • onProgreddUpdate(Progress...):在UI线程上接受doInBackground()传递过来的进度信息,并在UI线程上展示进度信息,它执行的时机是不确定的。
    • onPostExecute(Result):在UI线程上操作doInBackground()执行的返回值。

      上面介绍的四个步骤的示意图:

    AsyncTask取消任务

      在程序的任何位置,都可以通过cancel(boolean)方法进行取消任务,当取消任务之后,会改变isCancelled()的返回值,使其返回true。之后会调用onCancelled(Object)方法,替代onPostExecute()得到doInBackground()的返回结果。在运行中,可以经常通过isCancelled()方法查看任务是否被取消。

    AsyncTask的使用规则

      使用AsyncTask必须遵循以下规则:

    • AsyncTask必须声明在UI线程上。
    • AsyncTask必须在UI线程上实例化。
    • 必须通过execute()方法执行任务。
    • 不可以直接调用onPreExecute()、onPostExecute(Resut)、doInBackground(Params...)、onProgressUpdate(Progress...)方法。
    • 可以设置任务只执行一次,如果企图再次执行会报错。

    示例

      一个简单的示例,通过AsyncTask下载一个网络上的图片,下载的时候展示一个等待框,并显示在一个ImageView中。

      实现代码:

     1 package com.bgxt.datatimepickerdemo;
     2 
     3 import org.apache.http.HttpEntity;
     4 import org.apache.http.HttpResponse;
     5 import org.apache.http.client.HttpClient;
     6 import org.apache.http.client.methods.HttpGet;
     7 import org.apache.http.impl.client.DefaultHttpClient;
     8 import org.apache.http.util.EntityUtils;
     9 
    10 import android.app.Activity;
    11 import android.app.ProgressDialog;
    12 import android.graphics.Bitmap;
    13 import android.graphics.BitmapFactory;
    14 import android.os.AsyncTask;
    15 import android.os.Bundle;
    16 import android.view.View;
    17 import android.widget.Button;
    18 import android.widget.ImageView;
    19 
    20 public class AsyncTaskActivity1 extends Activity {
    21     private Button btnDown;
    22     private ImageView ivImage;
    23     private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
    24     private ProgressDialog dialog;
    25 
    26     @Override
    27     protected void onCreate(Bundle savedInstanceState) {
    28         // TODO Auto-generated method stub
    29         super.onCreate(savedInstanceState);
    30         setContentView(R.layout.asynctask_activity);
    31 
    32         btnDown = (Button) findViewById(R.id.btnDown);
    33         ivImage = (ImageView) findViewById(R.id.ivSinaImage);
    34         
    35         // 声明一个等待框以提示用户等待
    36         dialog=new ProgressDialog(this);
    37         dialog.setTitle("提示信息");
    38         dialog.setMessage("正在下载,请稍后...");
    39         
    40         btnDown.setOnClickListener(new View.OnClickListener() {
    41 
    42             @Override
    43             public void onClick(View v) {
    44                 // 执行一个异步任务,并把图片地址以参数的形式传递进去
    45                 new MyTask().execute(image_path);
    46             }
    47         });
    48     }
    49 
    50     // 以String类型的参数,Void表示没有进度信息,Bitmap表示异步任务返回一个位图
    51     public class MyTask extends AsyncTask<String, Void, Bitmap> {
    52         // 表示任务执行之前的操作
    53         @Override
    54         protected void onPreExecute() {
    55             super.onPreExecute();
    56             //显示等待框
    57             dialog.show();
    58         }
    59 
    60         //主要是完成耗时操作
    61         @Override
    62         protected Bitmap doInBackground(String... params) {
    63             HttpClient httpClient=new DefaultHttpClient();
    64             HttpGet httpGet=new HttpGet(params[0]);
    65             Bitmap bitmap=null;
    66             try {
    67                 //从网络上下载图片
    68                 HttpResponse httpResponse =httpClient.execute(httpGet);
    69                 if(httpResponse.getStatusLine().getStatusCode()==200){
    70                     HttpEntity httpEntity = httpResponse.getEntity();
    71                     byte[] data=EntityUtils.toByteArray(httpEntity);
    72                     bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);                    
    73                 }
    74             } catch (Exception e) {
    75                 e.printStackTrace();
    76             }
    77             return bitmap;
    78         }
    79         
    80         //完成更新UI操作
    81         @Override
    82         protected void onPostExecute(Bitmap result) {
    83             // TODO Auto-generated method stub
    84             super.onPostExecute(result);
    85             //设置ImageView的显示图片
    86             ivImage.setImageBitmap(result);
    87             // 销毁等待框
    88             dialog.dismiss();
    89         }
    90 
    91     }
    92 }

      效果展示:

      

      上面的Demo并没有用到进度的信息,下面再提供一个完整的AsyncTask的Demo,同样是下载一个图片,并且展示到一个ImageView中,但是这里在下载的过程中增加一个进度条对话框,用于展示下载的进度。

      实现代码:

      1 package com.bgxt.datatimepickerdemo;
      2 
      3 import java.io.ByteArrayOutputStream;
      4 import java.io.InputStream;
      5 
      6 import org.apache.http.HttpResponse;
      7 import org.apache.http.client.HttpClient;
      8 import org.apache.http.client.methods.HttpGet;
      9 import org.apache.http.impl.client.DefaultHttpClient;
     10 
     11 import android.app.Activity;
     12 import android.app.ProgressDialog;
     13 import android.graphics.Bitmap;
     14 import android.graphics.BitmapFactory;
     15 import android.os.AsyncTask;
     16 import android.os.Bundle;
     17 import android.view.View;
     18 import android.widget.Button;
     19 import android.widget.ImageView;
     20 
     21 public class AsyncTaskActivity2 extends Activity {
     22     private Button btnDown;
     23     private ImageView ivImage;
     24     private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
     25     private ProgressDialog dialog;
     26 
     27     @Override
     28     protected void onCreate(Bundle savedInstanceState) {
     29         super.onCreate(savedInstanceState);
     30         setContentView(R.layout.asynctask_activity);
     31         btnDown = (Button) findViewById(R.id.btnDown);
     32         ivImage = (ImageView) findViewById(R.id.ivSinaImage);
     33 
     34         dialog = new ProgressDialog(this);
     35         dialog.setTitle("提示");
     36         dialog.setMessage("正在下载,请稍后...");
     37         dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
     38         dialog.setCancelable(false);
     39 
     40         btnDown.setOnClickListener(new View.OnClickListener() {
     41 
     42             @Override
     43             public void onClick(View v) {
     44                 //  执行异步任务
     45                 new MyTask().execute(image_path);
     46             }
     47         });
     48     }
     49 
     50     public class MyTask extends AsyncTask<String, Integer, Bitmap> {
     51         @Override
     52         protected void onPreExecute() {
     53             super.onPreExecute();
     54             dialog.show();
     55         }
     56 
     57         @Override
     58         protected void onProgressUpdate(Integer... values) {
     59             super.onProgressUpdate(values);
     60             // 设置进度对话框的进度值
     61             dialog.setProgress(values[0]);
     62         }
     63 
     64         @Override
     65         protected void onPostExecute(Bitmap result) {
     66             super.onPostExecute(result);
     67             dialog.dismiss();
     68             ivImage.setImageBitmap(result);
     69         }
     70 
     71         @Override
     72         protected Bitmap doInBackground(String... params) {
     73             Bitmap bitmap = null;
     74             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     75             InputStream inputStream = null;
     76             try {
     77                 HttpClient httpClient = new DefaultHttpClient();
     78                 HttpGet httpGet = new HttpGet(params[0]);
     79                 HttpResponse httpResponse = httpClient.execute(httpGet);
     80                 if (httpResponse.getStatusLine().getStatusCode() == 200) {
     81                     inputStream = httpResponse.getEntity().getContent();
     82                     long file_length = httpResponse.getEntity()
     83                             .getContentLength();
     84                     int len = 0;
     85                     byte[] data = new byte[1024];
     86                     int total_length = 0;
     87                     // 以字节的方式读取图片数据
     88                     while ((len = inputStream.read(data)) != -1) {
     89                         total_length += len;
     90                         // 计算进度
     91                         int values = (int) ((total_length / (float) file_length) * 100);
     92                         // 发布进度信息
     93                         publishProgress(values);
     94                         outputStream.write(data, 0, len);
     95                     }
     96                     byte[] result=outputStream.toByteArray();
     97                     bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);
     98                 }
     99             } catch (Exception e) {
    100                 e.printStackTrace();
    101             } finally {
    102                 try {
    103                     if (inputStream != null) {
    104                         inputStream.close();
    105                     }
    106                 } catch (Exception e2) {
    107                 }
    108             }
    109             return bitmap;
    110         }
    111     }
    112 }

      实现效果:

      源码下载

     

  • 相关阅读:
    Java 基础 | 命名和运算
    JSON类型解析
    Python 实例方法、类方法、静态方法的区别与作用
    Python中logging模块的基本用法
    python中局部变量和全局变量
    C# 中 引用类型和值类型
    VS2008+SVN插件的使用
    使用linq to xml 怎么减小内存消耗
    linq to xml 中SaveOptions和LoadOptions的介绍
    C# 中==和Equals方法在引用类型中的区别
  • 原文地址:https://www.cnblogs.com/plokmju/p/android_AsyncTask.html
Copyright © 2011-2022 走看看