Android异步任务AsyncTask
为什么要使用异步任务?
我们知道安卓中更新UI组件必须在UI线程(主线程)中进行更新,为了避免UI线程被阻塞而失去响应,Android一般建议将耗时的操作放在新线程中完成,但是新线程也可能需要动态更新UI组件,比如需要从网上下载一张图片然后在ImageView中显示出来,这时就应该将链接网络,获取网络数据的操作放在新线程中完成:问题是在获取网络资源之后新线程不了允许直接更新UI组件,这个时候就需要用到异步处理了。
异步处理除了使用Handler类传递消息处理之外还有一种更加轻量级的处理方式AsycnTask,适用于简单的异步处理,不需要借助线程和Handler就可以实现
AsycnTask类基本介绍:
AsycnTask<Params,Progress,Result>是一个抽象类,通常用于被继承,继承这个类需要指定如下的三个泛型参数
Params:启动任务执行的输入参数类型
Progress:后台任务完成的进度值类型
Result:后台执行任务完成返回的结果类型
AsycnTask的方法介绍:
doInBackground(Params...param):使用AsycnTask必须重写这个方法,重写这个方法就是放后台线程要完成的任务。在这个方法中可以调用publishProgress(Progress..values)方法更新任务的执行进度
onPreExecute():这个方法会在执行后台耗时操作前被系统调用,也就是会在doInBackground(Params...param)方法前执行,一般在这个方法中完成一些初始化操作,比如让原本隐藏的进度条显示出来
onPostExecute(Result result):当执行完doInBackground(Params...param)方法时系统会自动调用这个方法,并且doInBackground方法返回的值会传递给这个方法
onProgressUpdate():在doInBackground(Params...param)方法中调用publishProgress(Progress..values)方法更新任务进度后会自动调用这个方法
execute():有AsycnTask的子类的实例对象调用,用于启动耗时任务
注意点:
- AsycnTask的doInBackground(Params...param)、onPreExecute()、onPostExecute(Result result)、onProgressUpdate()四个方法不可以自己手动调用,这四个方法是在调用execute()方法之后由系统自动调用的。
- 执行UI更新的操作不能在doInBackground(Params...param)方法中进行,可以在onPreExecute()、onPostExecute(Result result)、onProgressUpdate()三个方法中任一一个方法中进行,但是要区别出这几个方法执行的先后顺序,否则就算执行了UI组件更行也可能因为在耗时操作之前执行而没有任何效果。
- 必须在UI线程中创建AsycnTask的实例
- 使用AsycnTask的实例调用execute()方法时必须在UI线程中
以下源代码的功能介绍:通过网上图片的地址调用将图片显示在APP中的ImageView中,当图片还没加载出来前显示进度条,图片加载出来之后隐藏进度条
Activity_main.xml布局文件:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:orientation="vertical"> 5 6 7 <Button 8 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:onClick="btn" 12 android:text="提交" /> 13 14 15 <ProgressBar 16 android:id="@+id/bar" 17 android:layout_width="match_parent" 18 android:layout_height="wrap_content" 19 android:padding="20px" 20 android:visibility="gone" /> 21 22 <ImageView 23 android:id="@+id/ima" 24 android:layout_width="wrap_content" 25 android:layout_height="wrap_content" /> 26 27 28 </LinearLayout>
Activity_main.java源代码:
1 package com.contentprovide.liuliu.asynctaskdemo; 2 3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.os.AsyncTask; 6 import android.support.v7.app.AppCompatActivity; 7 import android.os.Bundle; 8 import android.view.View; 9 import android.widget.Button; 10 import android.widget.ImageView; 11 import android.widget.ProgressBar; 12 13 import java.io.BufferedInputStream; 14 import java.io.BufferedReader; 15 import java.io.IOException; 16 import java.io.InputStream; 17 import java.net.URL; 18 import java.net.URLConnection; 19 20 public class MainActivity extends AppCompatActivity { 21 22 ProgressBar bar; 23 String url = new String("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514633107382&di=6811991b77bb94183ecfc91296644c53&imgtype=0&src=http%3A%2F%2Fimage.tianjimedia.com%2FuploadImages%2F2014%2F289%2F01%2FIGS09651F94M.jpg"); 24 ImageView ima; 25 26 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 super.onCreate(savedInstanceState); 30 setContentView(R.layout.activity_main); 31 ima = (ImageView) findViewById(R.id.ima); 32 bar = (ProgressBar) findViewById(R.id.bar); 33 34 35 } 36 37 public void btn(View view) { 38 new MyAsyncTask().execute(url);//execute方法必须在UI线程中调用 39 } 40 41 // 自定义内部类继承AsuncTask 42 class MyAsyncTask extends AsyncTask<String, Void, Bitmap> { 43 44 @Override//在doInBackground()方法前执行 45 protected void onPreExecute() { 46 super.onPreExecute(); 47 bar.setVisibility(View.VISIBLE);//设置进度条可见 48 } 49 50 @Override 51 protected Bitmap doInBackground(String... strings) { 52 Bitmap bitmap = null; 53 try { 54 Thread.sleep(3000); 55 // 获取传进来的URL值 56 String url = strings[0]; 57 try { 58 URLConnection urlConnection = new URL(url).openConnection(); 59 InputStream inputStream = urlConnection.getInputStream(); 60 // 通过decodeStream解析输入流 61 bitmap = BitmapFactory.decodeStream(inputStream); 62 63 64 } catch (IOException e) { 65 e.printStackTrace(); 66 } 67 68 69 } catch (InterruptedException e) { 70 e.printStackTrace(); 71 } 72 73 74 return bitmap; 75 76 } 77 78 79 @Override 80 protected void onPostExecute(Bitmap bitmap) { 81 super.onPostExecute(bitmap); 82 bar.setVisibility(View.GONE);//设置进度条不可见 83 ima.setImageBitmap(bitmap);//把从网上获取到的图片资源设置到ImageView中 84 } 85 } 86 87 }