Android_AsyncTask

一.AsyncTask的简介
       在Android中实现异步任务机制有两种方式,Handler和AsyncTask。
Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一下。为了简化操作Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。
       AsyncTask,即异步任务,是Android给我们提供的一个处理异步任务的类.通过此类,可以实现UI线程和后台线程进行通讯,后台线程执行异步任务,并把结果返回给UI线程.
       我通常会把代码的逻辑想成现实生活中的某些现象,加以理解!以前的博客的都没有把这类想法写在博客,是怕误导别人!以后的博客我会加上这部分,仅仅是为了自己的回忆和理解!
       AsyncTask,为什么需要这个东西呢?
       因为每个程序就只有一个主线程,就像我们公司中某个项目的项目管理者,负责展示项目(显示UI)等操作,可是他不可能一个人做完一整个项目,需要其他人的帮忙做其他的事情,这也就好比是线程了!让线程去做一些耗时的操作,然后做完就告诉项目负责人,做完了,可以更新我们的项目了(更新UI)!那帮忙做事的人也不可能就一个人,一个人的效率太低了,可能已一队人,也就是线程池了!AsyncTask也就是把这一麻烦的过程给封装好了,可以理解为AsyncTask是这个过程规范!
二.AsyncTask的方法
       构建AsyncTask子类的泛型参数
AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承.继承AsyncTask需要指定如下三个泛型参数:
Params:启动任务时输入的参数类型.
Progress:后台任务执行中返回进度值的类型.
Result:后台任务执行完成后返回结果的类型.
       构建AsyncTask子类的回调方法
AsyncTask主要有如下几个方法:
doInBackground:必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成.
onPreExecute:执行后台耗时操作前被调用,通常用于进行初始化操作.
onPostExecute:当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法.通过此方法进行UI的更新.
        onProgressUpdate:当在doInBackground方法中调用publishProgress方法更新任务执行进度后,将调用此方法.通过此方法我们可以知晓任务的完成进度.
三.示例
       演示一个典型的异步处理的实例--加载网络图片.网络操作作为一个不稳定的耗时操作,从4.0开始就被严禁放入主线程中.所以在显示一张网络图片时,我们需要在异步处理中下载图片,并在UI线程中设置图片。
       代码中主要是onPreExecute,doInBackground,onPostExecute方法中进行操作,我们可以理解为:项目的负责人发布了一项任务,需要完成,因此他用AsyncTask这个规范去执行(execute()),任何的任务都基本是三个部分,事前准备(onPreExecute),执行工作(doInBackground),完成结果(onPostExecute)!
       好了,看下界面效果和代码,自己联想下!
       还有一点,这里用到网络操作,记得加权限喔!
<uses-permission android:name="android.permission.INTERNET"/>

 

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.liangdianshui.asynctaskdemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.BitmapFactory;  
  6. import android.os.AsyncTask;  
  7. import android.os.Bundle;  
  8. import android.view.View;  
  9. import android.widget.ImageView;  
  10. import android.widget.ProgressBar;  
  11.   
  12. import java.io.BufferedInputStream;  
  13. import java.io.IOException;  
  14. import java.io.InputStream;  
  15. import java.net.URL;  
  16. import java.net.URLConnection;  
  17.   
  18. public class DownloadImageActivity extends Activity {  
  19.   
  20.     private ProgressBar mProgress;  
  21.     private ImageView mIvDownloadImage;  
  22.     private static String Url ="http://img5.imgtn.bdimg.com/it/u=794383953,3828916890&fm=21&gp=0.jpg";  
  23.     @Override  
  24.     protected void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.activity_download_image);  
  27.         initView();  
  28.         new MyAsyncTask().execute(Url);  
  29.     }  
  30.   
  31.     private void initView() {  
  32.         mProgress = (ProgressBar) findViewById(R.id.progress);  
  33.         mIvDownloadImage = (ImageView) findViewById(R.id.iv_image_download);  
  34.     }  
  35.   
  36.     /** 
  37.      * Params:启动任务时输入的参数类型. doInBackground() 
  38.      * Progress:后台任务执行中返回进度值的类型.onProgressUpdate() 
  39.      * Result:后台任务执行完成后返回结果的类型.onPostExecute() 
  40.      */  
  41.     class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {  
  42.   
  43.         //进行异步任务的处理.  
  44.         @Override  
  45.         protected Bitmap doInBackground(String... params) {  
  46.             //获取传进来的第一个参数  
  47.             String url = params[0];  
  48.             Bitmap bitmap = null;  
  49.             try {  
  50.                 /** 
  51.                  * No address associated with hostname 
  52.                  * 报上面的错误原因:1.没有设置连网的权限  2.手机没开网络 
  53.                  */  
  54.                 //打开链接  
  55.                 URLConnection urlConnection = new URL(url).openConnection();  
  56.                 InputStream inputStream = urlConnection.getInputStream();  
  57.                 BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);  
  58.                 //为了更清楚的显示,在线程休眠3s  
  59.                 Thread.sleep(3000);  
  60.                 bitmap = BitmapFactory.decodeStream(bufferedInputStream);  
  61.                 //记得关闭流  
  62.                 bufferedInputStream.close();  
  63.                 inputStream.close();  
  64.             } catch (IOException e) {  
  65.                 e.printStackTrace();  
  66.             } catch (InterruptedException e) {  
  67.                 e.printStackTrace();  
  68.             }  
  69.             return bitmap;  
  70.         }  
  71.   
  72.         //异步处理前的操作  
  73.         @Override  
  74.         protected void onPreExecute() {  
  75.             super.onPreExecute();  
  76.             //将ProgressBar设置为可见的  
  77.             mProgress.setVisibility(View.VISIBLE);  
  78.         }  
  79.   
  80.         //异步处理后的操作  
  81.         //bitmap是doInBackground操作后返回的值  
  82.         @Override  
  83.         protected void onPostExecute(Bitmap bitmap) {  
  84.             super.onPostExecute(bitmap);  
  85.             //操作完成后把进程显示隐藏,并把异步下载的图片显示在ImageView中  
  86.             mProgress.setVisibility(View.GONE);  
  87.             mIvDownloadImage.setImageBitmap(bitmap);  
  88.         }  
  89.     }  
  90. }  

第二个示例是“加载进条”
我们看下示例的效果吧:

 

          这里看起来好像没啥问题啊,可是仔细看,你会发现,当加载进度条加载到一半的时候,你按返回键,再加载进度条,你会发现,要等待一段时间才会加载!这是为什么呢?
       因为:AsyncTask是基于线程池进行实现的,当一个线程没有结束时,后面的线程是不能执行的.所以必须等到第一个task的for循环结束后,才能执行第二个task.我们知道,当点击BACK键时会调用Activity的onPause()方法.为了解决这个问题,我们需要在Activity的onPause()方法中将正在执行的task标记为cancel状态,在doInBackground方法中进行异步处理时判断是否是cancel状态来决定是否取消之前的task.
        这就好像是项目的负责人,发布了一项任务,那一队人就在干这项任务(线程池执行操作,也就是doInBackground方法的操作),好了今天做到一半,明天上班上班,会继续干这个任务,而不会停下来,重新执行这个任务或者干另一个任务!因为他没有接收到负责人的命令!因此当按了返回键的时候,我们再点击加载进度条,项目的负责人需要告诉他们这个项目暂时不做了(也就是把执行的task标记为cancel状态),然后工人就判断这个任务是否有这个状态,有这个状态就停止不干了!
        加上了cancel后的效果图是这样的:

 

 

代码:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.liangdianshui.asynctaskdemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.AsyncTask;  
  5. import android.os.Bundle;  
  6. import android.widget.ProgressBar;  
  7.   
  8. public class ProgressActivity extends Activity {  
  9.   
  10.     private ProgressBar mProgress;  
  11.     private MyAsyncTask mAsyncTask;  
  12.   
  13.     @Override  
  14.     protected void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.activity_progress);  
  17.         mProgress = (ProgressBar) findViewById(R.id.pro_show_progress);  
  18.         mAsyncTask=new MyAsyncTask();  
  19.         mAsyncTask.execute();  
  20.     }  
  21.   
  22.     class MyAsyncTask extends AsyncTask<Void, Integer, Void> {  
  23.         @Override  
  24.         protected void onPreExecute() {  
  25.             super.onPreExecute();  
  26.             mProgress.setProgress(0);  
  27.         }  
  28.   
  29.         @Override  
  30.         protected void onProgressUpdate(Integer... values) {  
  31.             super.onProgressUpdate(values);  
  32.             mProgress.setProgress(values[0]);  
  33.         }  
  34.   
  35.         @Override  
  36.         protected void onPostExecute(Void aVoid) {  
  37.             super.onPostExecute(aVoid);  
  38.         }  
  39.   
  40.         @Override  
  41.         protected Void doInBackground(Void... params) {  
  42.             for (int i = 0; i < 100; i++) {  
  43.                 //如果task是cancel状态,则终止for循环  
  44.                 if (isCancelled()) {  
  45.                     break;  
  46.                 }  
  47.                 //调用publishProgress方法将自动触发onProgressUpdate方法,把参数传进去,来进行进度条的更新.  
  48.                 publishProgress(i);  
  49.                 try {  
  50.                     Thread.sleep(50);  
  51.                 } catch (InterruptedException e) {  
  52.                     e.printStackTrace();  
  53.                 }  
  54.             }  
  55.             return null;  
  56.         }  
  57.     }  
  58.   
  59.     ;  
  60.   
  61.     @Override  
  62.     protected void onPause() {  
  63.         super.onPause();  
  64.         if (mAsyncTask != null && mAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {  
  65.             //cancel方法只是将对应的AsyncTask标记为cancelt状态,并不是真正的取消线程的执行.  
  66.             mAsyncTask.cancel(true);  
  67.         }  
  68.     }  
  69. }  

 

好了,胡说八道完了!

示例的Demo:http://download.csdn.net/detail/two_water/9510336

posted @ 2017-04-23 22:09  天涯海角路  阅读(109)  评论(0)    收藏  举报