• Android 异步加载数据 AsyncTask异步更新界面


    官方文档:
        AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
        AsyncTask能够更恰当和更简单的去使用UI线程。这个类允许执行后台操作和展现结果在UI线程上,无需操纵线程和/或处理程序。AsyncTask的内部实现是一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+Handler的方式调用回调函数。
       
    1.AsyncTask抽象出后台线程运行的五个状态:
        分别是:1、准备运行,2、正在后台运行,3、进度更新,4、完成后台任务,5、取消任务,对于这五个阶段,AsyncTask提供了五个回调函数:

        1、准备运行:onPreExecute(),该回调函数在任务被执行之后立即由UI线程调用。这个步骤通常用来建立任务,在用户接口(UI)上显示进度条。
        2、正在后台运行:doInParams...),该回调函数由后台线程在onPreExecute()方法执行结束后立即调用。通常在这里执行耗时的后 台计算。计算的结果必须由该函数返回,并被传递到onPostExecute()中。在该函数内也可以使用 publishProgress(Progress...)来发布一个或多个进度单位(unitsof progress)。这些值将会在onProgressUpdate(Progress...)中被发布到UI线程。
        3. 进度更新:onProgressUpdate(Progress...),该函数由UI线程在publishProgress(Progress...)方法调用完后被调用。一般用于动态地显示一个进度条。
        4. 完成后台任务:onPostExecute(Result),当后台计算结束后调用。后台计算的结果会被作为参数传递给这一函数。
        5、取消任务:onCancelled (),在调用AsyncTask的cancel()方法时调用
    2.使用:
        AsyncTask必须使用子类。子类会覆盖至少一个方法(doInParams…)),通常将覆盖第二个(onPostExecute(结果)。
    AsyncTask的构造函数有三个模板参数:<Params, Progress, Result>

      1.Params,传递给后台任务的参数类型。
      2.Progress,后台计算执行过程中,进步单位(progress units)的类型。(就是后台程序已经执行了百分之几了。)
      3.Result, 后台执行返回的结果的类型。
      AsyncTask并不总是需要使用上面的全部3种类型。标识不使用的类型很简单,只需要使用Void类型即可。

      1     import java.io.InputStream;
      2 
      3     import java.net.HttpURLConnection;
      4 
      5     import java.net.URL;
      6 
      7     import android.app.Activity;
      8 
      9     import android.graphics.Bitmap;
     10 
     11     import android.graphics.BitmapFactory;
     12 
     13     import android.os.AsyncTask;
     14 
     15     import android.os.Bundle;
     16 
     17     import android.view.View;
     18 
     19     import android.view.View.OnClickListener;
     20 
     21     import android.widget.Button;
     22 
     23     import android.widget.ImageView;
     24 
     25     import android.widget.ProgressBar;
     26 
     27     import android.widget.Toast;
     28 
     29     /**
     30 
     31     * AsyncTask  实现异步加载图片
     32 
     33     */
     34     public class MainActivity extends Activity {
     35 
     36                                                                                                                                            
     37 
     38         public static  final String IMG_URL="http://images.51cto.com/images/index/Images/Logo.gif";
     39 
     40         Button btn_asynctask;
     41 
     42         ImageView imgView;
     43 
     44         ProgressBar progressBar;
     45 
     46         protected void onCreate(Bundle savedInstanceState) {
     47 
     48             super.onCreate(savedInstanceState);
     49 
     50             setContentView(R.layout.activity_main);
     51 
     52             //加载控件
     53 
     54             imgView = (ImageView) this.findViewById(R.id.imageView);
     55 
     56             btn_asynctask = (Button) this.findViewById(R.id.btn_AsyncTask);
     57 
     58             progressBar = (ProgressBar) this.findViewById(R.id.progressBar);
     59 
     60             //绑定监听器
     61 
     62             btn_asynctask.setOnClickListener(new OnClickListener() {
     63 
     64                 @Override
     65 
     66                 public void onClick(View v) {
     67 
     68                     GetImgTask getImgTask = new GetImgTask();
     69 
     70                     getImgTask.execute(IMG_URL); //执行该任务
     71 
     72                 }
     73 
     74             });
     75 
     76         }
     77 
     78                                                                                                                                            
     79 
     80         /**获取网络图片任务**/
     81 
     82         private class GetImgTask extends AsyncTask<String, Integer, Bitmap> {
     83 
     84                                                                                                                                                 
     85 
     86             /**在 doInParams...)之前被调用,在ui线程执行   **/
     87 
     88             @Override
     89 
     90             protected void onPreExecute() {
     91 
     92                  imgView.setImageBitmap(null);
     93 
     94                  progressBar.setProgress(0);    //进度条复位
     95 
     96             }
     97 
     98                                                                                                                                                 
     99 
    100             /**在后台线程中执行的任务**/
    101             protected Bitmap doInString...  params) {
    102 
    103                                                                                                                                                     
    104 
    105                 publishProgress(0); //会调用onProgressUpdate更新界面
    106 
    107                                                                                                                                                     
    108                 InputStream inputStream = null;
    109                 Bitmap imgBitmap = null;
    110                 try {
    111 
    112                     URL url = new URL(IMG_URL);
    113 
    114                     if(url != null) {
    115 
    116                         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    117 
    118                         connection.setConnectTimeout(2000);
    119 
    120                         connection.setDoInput(true);
    121 
    122                         connection.setRequestMethod("GET");
    123 
    124                         int code = connection.getResponseCode();
    125 
    126                         if(200 == code) {
    127 
    128                             inputStream = connection.getInputStream();
    129 
    130                             imgBitmap = BitmapFactory.decodeStream(inputStream);
    131 
    132                         }
    133 
    134                     }
    135 
    136                 } catch (Exception e) {
    137 
    138                     e.printStackTrace();
    139 
    140                     return null;
    141 
    142                 }
    143 
    144                 publishProgress(100); //下载完成,更新进度条为满格
    145 
    146                 //这里不是UI线程,故不能直接setImage(imgBitmap),
    147 
    148                 return imgBitmap;
    149 
    150             }
    151 
    152                                                                                                                                                 
    153 
    154             /**在调用publishProgress之后被调用,在ui线程执行  **/
    155 
    156             @Override
    157 
    158             protected void onProgressUpdate(Integer... values) {
    159 
    160                 progressBar.setProgress(values[0]);  //设置进度条的进度
    161 
    162             }
    163 
    164             /**在后台线程执行完成之后,调用该方法,获取数据更新界面**/
    165 
    166             @Override
    167 
    168             protected void onPostExecute(Bitmap result) {
    169 
    170                 if(result != null) {
    171 
    172                     Toast.makeText(MainActivity.this, "成功获取图片", Toast.LENGTH_LONG).show();
    173 
    174                     imgView.setImageBitmap(result);
    175 
    176                 }else {
    177 
    178                     Toast.makeText(MainActivity.this, "获取图片失败", Toast.LENGTH_LONG).show();
    179 
    180                 }
    181             }
    182 
    183             /**取消任务,在ui线程执行 **/
    184             protected void onCancelled() {
    185 
    186                 progressBar.setProgress(0);//进度条复位
    187 
    188                 super.onCancelled();
    189             }
    190         }
    191     }

    分析:

        1.点击按钮之后,创建一个任务,参数值为url(所以第一个参数为String)

        2.UI线程执行onPreExecute(),把ImageView的图片清空,progrssbar的进度清零。
        3.后台线程执行doInBackground(),不可以在doInBackground()操作ui,调用publishProgress(0)更新 进度,此时会调用onProgressUpdate(Integer...progress)更新进度条(进度用整形表示,因此AsyncTask的第二 个模板参数是Integer)。函数最后返回result(例子中是返回Bitmap类型,因此AsyncTask的第三个模板参数是Bitmap)。
        4.当后台任务执行完成后,调用onPostExecute(Result),传入的参数是doInBackground()中返回的对象。

    这世界上有一种鸟是没有脚的,它只能够一直的飞呀飞呀,飞累了就在风里面睡觉,这种鸟一辈子只能下地一次,那一次就是它死亡的时候。
  • 相关阅读:
    Android应用性能优化
    打造高质量Android应用:Android开发必知的50个诀窍
    毕向东day23--java基础-网络总结
    《编写高质量代码:改善Java程序的151个建议》
    最新java数组的详解
    主线程中一定不能放耗时操作,必须要开子线程,比如下载文件,不然会不让你拿到输入流--报错显示android.os.NetworkOnMainThreadException
    《Head First设计模式(中文版)》
    码表由来:ascll码-Gbk2312-GBK-Unicode-UTF-8
    《Java程序性能优化:让你的Java程序更快、更稳定》
    LeetCode 147. 对链表进行插入排序
  • 原文地址:https://www.cnblogs.com/xuyinghui/p/4665179.html
Copyright © 2020-2023  润新知