zoukankan      html  css  js  c++  java
  • Android攻城狮AsyncTask

    构建AsyncTack子类的参数
    AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承,继承AsyncTask需要指定如下三个泛型参数:
    params:启动任务时输入参数的类型。
    progress:后台任务执行中,返回进度值的类型。
    Result:后台执行任务完成后,返回结果的类型。
    ------------------------
    如何构建AsyncTask子类的回调方法?
    一个完整的AsyncTask通常需要指定如下几个方法:
    1. doInBackground:这是AsyncTask子类所必须要重写的方法,异步执行后台线程将要完成的任务。我们所有的耗时操作都将在这个方法中进行操作。
    2. onPreExecute:执行后台耗时操作之前被调用,通常是用户完成一些初始化操作。
    3. onPostExecute:当doInBackground()完成后,系统会自动调用此方法,并将doInBackground()返回的值传给该方法,也就是展示处理完成的结果。
    4. onProgressUpdate:在doInBackground()方法中调用publishProgrsss()更新任务的执行进度后,就会触发该方法(必须先调用publishProgrsss()),就可以知道当前耗时操作的完成进度。
    ----------------------------------
    额外补充:
    1. 注意这里的例子继承的是 AsyncTask<Void,Void,Void>,需要带上三个泛型,定义Void泛型要注意V是大写。。。
    2. 执行顺序:onPrRreExecute() --> doInBackground() --> onProgressUpdate()  --> onPostExecute()。



    AsyncTask<String,Void,Bitmap>三个参数分别为:url类型,进度值类型,返回值类型。
    这里的例子暂时不设置进度值,url设置为String类型,又因为我们加载的是一张Bitmap,所以返回的参数类型设置为 Bitmap。
    1. doInBackground(String...params)传进来的是一个可变长数组,也就是说,我们可以传进不止一个参数(通过execute()传进来),这些参数依次存在于这个数组中。现在只有一个参数,所以只要写个params[0]取出对应的URL即可。
    2. 定义一个Bitmap,也就是我们所要获取的Bitmap。
    3. 定义一个访问网络的URLconnection,也就是一个网络连接对象connection。
    4. 定义一个InputStream,用于获取数据的输入流。
    5. 初始化connection:connection = new URL(url).openConnection();这里需要自行导入jar包:import java.net.URL; 另外需要try-catch包围。
    6. 获取输入流:is = connection.getInputStream();
    7. 对输入流进行包装:BufferedInputStream bis = new BufferedInputStream(is);
    8. 通过decodeStream()将输入流解析成 Bitmap:bitmap = BitmapFactory.decodeStream(bis);
    9. 关闭输入流、返回 bitmap。

     
      1 //Asynctask加载网络图片 
      2 //使用ProgressBar 和ProgressDialog提示下载的进度
      3 
      4 public class ImageTest extends Activity {
      5     private ImageView imageView;
      6     private ProgressBar progressBar;// 方式一:对话框提示进度
      7     String URL = "http://p4.so.qhimgs1.com/sdr/1228_768_/t01f7ed810efbfe800a.jpg";
      8     ProgressDialog dialog;// 方式二:对话框提示进度
      9     MyAsynctask1 task;
     10 
     11     @Override
     12     protected void onCreate(Bundle savedInstanceState) {
     13         // TODO Auto-generated method stub
     14         super.onCreate(savedInstanceState);
     15         setContentView(R.layout.image);
     16         imageView = (ImageView) findViewById(R.id.image);
     17         progressBar = (ProgressBar) findViewById(R.id.bar);
     18 
     19         dialog = new ProgressDialog(this);
     20         dialog.setTitle("提示信息:");
     21         dialog.setMessage("laoding....");
     22         dialog.setProgressStyle(dialog.STYLE_HORIZONTAL);
     23 
     24         MyAsynctask1 task = new MyAsynctask1();
     25         task.execute(URL);
     26 
     27     }
     28 
     29     // 不等进度条满就后退再执行,会发现后面执行的进度条迟迟没有响应,
     30     // 令AsyncTask的生命周期和Activity或者Fragment的生命周期保持一致就可以了。
     31     @Override
     32     protected void onPause() {
     33         // TODO Auto-generated method stub
     34         super.onPause();
     35         if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) {
     36             task.cancel(true);
     37             // cancel()只是将对应的task标记为cancel状态,并不是真正取消线程执行
     38         }
     39     }
     40 
     41     // params:启动任务时输入参数的类型。
     42     // progress:后台任务执行中,返回进度值的类型。
     43     // Result:后台执行任务完成后,返回结果的类型。
     44 
     45     // 2. 执行顺序:onPrRreExecute() --> doInBackground() --> onProgressUpdate() -->
     46     // onPostExecute()。
     47     class MyAsynctask1 extends AsyncTask<String, Integer, Bitmap> {
     48         @Override
     49         // 1.执行后台耗时操作之前被调用,通常是用户完成一些初始化操作。
     50         protected void onPreExecute() {
     51             // TODO Auto-generated method stub
     52             super.onPreExecute();
     53             // 显示进度条
     54             progressBar.setVisibility(View.VISIBLE);
     55             dialog.show();
     56         }
     57 
     58         // 4.当doInBackground()完成后,系统会自动调用此方法,并将doInBackground()返回的值传给该方法,也就是展示处理完成的结果。
     59         @Override
     60         protected void onPostExecute(Bitmap result) {
     61             // TODO Auto-generated method stub/
     62             super.onPostExecute(result);
     63             progressBar.setVisibility(View.GONE);// 消失进度条
     64             dialog.dismiss();
     65             imageView.setImageBitmap(result);
     66 
     67         }
     68 
     69         // 2.
     70         // doInBackground:这是AsyncTask子类所必须要重写的方法,异步执行后台线程将要完成的任务。我们所有的耗时操作都将在这个方法中进行操作。
     71         @Override
     72         protected Bitmap doInBackground(String... params) {
     73             // TODO Auto-generated method stub
     74 
     75             // 从params中取出参数值,传给url
     76             String url = params[0];
     77             // 初始化参数
     78             Bitmap bitmap = null;
     79             URLConnection connection;
     80             InputStream inputStream;
     81 
     82             try {
     83                 connection = new URL(url).openConnection();
     84                 inputStream = connection.getInputStream();// 获取输入流
     85                 BufferedInputStream bis = new BufferedInputStream(inputStream);
     86                 Thread.sleep(5000);// 睡3秒
     87                 // 通过decodeStream()解析输入流
     88                 bitmap = BitmapFactory.decodeStream(bis);
     89                 inputStream.close();
     90                 bis.close();
     91 
     92             } catch (IOException e) {
     93                 // TODO Auto-generated catch block
     94                 e.printStackTrace();
     95             } catch (InterruptedException e) {
     96                 // TODO Auto-generated catch block
     97                 e.printStackTrace();
     98             }
     99             // 模拟进度更新
    100             for (int i = 0; i < 100; i++) {
    101                 if (isCancelled()) {
    102                     break;
    103                 }
    104                 publishProgress(i);
    105 
    106             }
    107             return bitmap;
    108         }
    109 
    110         // 3.在doInBackground()方法中调用publishProgrsss()更新任务的执行进度后,就会触发该方法(必须先调用publishProgrsss()),就可以知道当前耗时操作的完成进度。
    111         @Override
    112         protected void onProgressUpdate(Integer... values) {
    113             // TODO Auto-generated method stub
    114             super.onProgressUpdate(values);
    115             if (isCancelled()) {
    116                 return;
    117 
    118             }
    119             dialog.setProgress(values[0]);
    120             progressBar.setProgress(values[0]);
    121         }
    122 
    123     }
    124 
    125 }




    反复执行上一节课的异步加载,而且是不等进度条满就后退再执行,会发现后面执行的进度条迟迟没有响应,为什么呢?这并非bug,而是 AsyncTask 所实行的一种机制。AsyncTask的底层是通过线程池去作用的。当一个线程没有完成的时候,后面的线程就无法开始。我们上一节课用了for()循环去执行进度条 的更新操作,必须等到for()循环结束后才会执行下一个Task。
    ---------
    那么,如何去解决这样的问题呢?
    很简单,令AsyncTask的生命周期和Activity或者Fragment的生命周期保持一致就可以了。
    回到ProgressBar,重写onPause(),在Activity执行onPause()的时候,对AsyncTask进行判断:
    如果AsyncTask不为空且处于Running状态,我们就要取消该线程:
        protected void onPause() {
            super.onPause();
            if(mTask!=null && mTask.getStatus()==AsyncTask.Status.RUNNING){
                mTask.cancel(true);
            }
        }
    cancle()方法只是将对应的AsyncTask标记为cancel状态,并不是真正地取消线程的执行。
    另外,我们在Java中也是没办法直接粗暴地停止一个线程,我们必须要等一个线程执行完毕之后才能继续其他线程的操作。
    --------------
    那要如何快速停止线程呢?
    1. 在onPause()中标记取消状态:mTask.cancel(true);
    既然我们已经标记了cancel状态,那么可以在AsyncTask中监测这样的改变,一旦当前状态改为cancelled,我们就要跳出循环,立刻结束当前操作,从而结束整个线程逻辑。
    2. 在doInBackground()方法的for()循环内添加isCancelled()对线程的状态进行判断:
    if(isCancelled())break;
    3. 同理,在onProgressUpdate()方法中也做类似的处理:
    if(isCancelled())return;
    通过如上操作,我们就能快速停止当前线程,将处理权交给下一个AsyncTask。
     1 public class ProgressBarTest extends Activity {
     2 
     3     ProgressBar progressBar;
     4     MyAsycnTask2 task;
     5     @Override
     6     protected void onCreate(Bundle savedInstanceState) {
     7         // TODO Auto-generated method stub
     8         super.onCreate(savedInstanceState);
     9         setContentView(R.layout.progressbar);
    10         progressBar = (ProgressBar) findViewById(R.id.progressBar1);
    11 
    12          task = new MyAsycnTask2();
    13         task.execute();
    14     }
    15 
    16     @Override
    17     protected void onPause() {
    18         // TODO Auto-generated method stub
    19         super.onPause();
    20         if (task!=null&&task.getStatus()==AsyncTask.Status.RUNNING) {
    21             task.cancel(true);//cancel()只是将对应的task标记为cancel状态,并不是真正取消线程执行
    22         }
    23     }
    24 
    25     class MyAsycnTask2 extends AsyncTask<Void, Integer, Void> {
    26 
    27         @Override
    28         protected void onProgressUpdate(Integer... values) {
    29             // TODO Auto-generated method stub
    30             // 获取进度更新值
    31             super.onProgressUpdate(values);
    32             if (isCancelled()) {
    33                 return;
    34             }
    35             progressBar.setProgress(values[0]);
    36         }
    37 
    38         @Override
    39         protected Void doInBackground(Void... params) {
    40             // TODO Auto-generated method stub
    41             
    42             // 模拟进度更新
    43             for (int i = 0; i < 100; i++) {
    44                 if (isCancelled()) {
    45                 break;
    46             }
    47                 publishProgress(i);
    48                 try {
    49                     Thread.sleep(300);
    50                 } catch (InterruptedException e) {
    51                     // TODO Auto-generated catch block
    52                     e.printStackTrace();
    53                 }
    54             }
    55             return null;
    56         }
    57     }
    58 }


  • 相关阅读:
    Springboot~多个数据源时自定义datasource的bean
    springboot~aspose操作word模板实现导出功能
    spring-security-jwt的总结与实现
    mybatis+maven自动生成代码框架
    chrome 插件 vimium 像操作vim一样的操作浏览器
    递归计算过程和迭代计算过程
    找工作--Java相关
    《Linux程序设计》--读书笔记---第十三章进程间通信:管道
    poj 1474 Video Surveillance
    动态包含与静态包含的区别
  • 原文地址:https://www.cnblogs.com/my334420/p/6724539.html
Copyright © 2011-2022 走看看