AsyncTask
1.AsyncTask介绍
除了使用 Handler实现线程间的通信外, Android提供了一个工具类 :AsyncTask, 它使创建需要与用户界面交互的长时间运行的任务变得更简单。相对来说AsyncTask更轻量级一些,适用于简单的异步处理,不需要借助线程和Handler即可实现。AsyncTask是抽象类。AsyncTask定义了三种泛型类型Params, Progress和Result.
- Params启动任务执行的输入参数,比如,HTTP 请求的URL。
- Progress后台任务执行的百分比。
- Result后台执行任务最终返回的结果,比如String。
2.AsyncTask的执行步骤
AsyncTask的执行分为四个步骤,每一步对应一个回调方法,我们需要的就是实现这些方法。
(1)首先定义一个类继承AsyncTask
(2)实现AsyncTask中定义的下面一个或几个方法。
四个执行步骤分别为:
(1) onPreExecute() :被UI Thread调用,该方法用来做- - 些准备工作,如在界面上显示-一个进度条。
(2) dolnBackground(Params…):将在onPreExecute之后执行,运行在后台线程中。负责执行耗时工作。可以调用publishProgress方法来更新实时任务进度。
(3) onProgressUpdate(Progress…) :在publishProgress方法被调用后,UI Thread将调用该方法在界面上展示任务的进展情况,例如通过一个进度条进行展示。
(4) onPostExecute(Result) :在doInBackground执行完成后,onPostExecute方法将被UI Thread调用,后台的计算结果将通过该方法传递到UI Thread。
package com.example.handler;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class Main2Activity extends AppCompatActivity {
private TextView info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
info=findViewById(R.id.info);
}
public void asyncTaskClick(View v){
new MyAsyncTask(this).execute();
}
/*
* 通过一个AsyncTask实现一个异步任务
* */
private static class MyAsyncTask extends AsyncTask<String,Integer,String>{
private Main2Activity activity;
public MyAsyncTask(Main2Activity activity){
this.activity=activity;
}
//执行任务之前触发的事件方法,可以在该方法中做一些初始化工作
@Override
protected void onPreExecute() {
super.onPreExecute();
System.out.println("onPreExecute");
activity.info.setText("开始执行任务...");
}
//执行后台任务的方法,类似于线程,所以不能再该方法中访问UI组件
@Override
protected String doInBackground(String... strings) {
for (int i=0;i<10;i++){
System.out.println(i);
publishProgress();//更新进度
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "success";
}
//更新进度值
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
activity.info.setText("当前的值为:"+values[0]);
}
//当doInBackground方法返回后被调用
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
activity.info.setText(s);
}
}
}
3.使用AsyncTask实现下载
package com.example.handler;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class Main2Activity extends AppCompatActivity {
private TextView info;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
info=findViewById(R.id.info);
progressBar=findViewById(R.id.progressBar);
}
public void downloadClick(View v){
new DownloadAsyncTask(this).execute("http://b-ssl.duitang.com/uploads/item/201604/28/20160428171505_PKnUm.thumb.700_0.jpeg");
}
private static class DownloadAsyncTask extends AsyncTask<String, Integer, Integer> {
private Main2Activity activity;
public DownloadAsyncTask(Main2Activity activity){
this.activity=activity;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
activity.progressBar.setProgress(0);
}
@Override
protected Integer doInBackground(String... strings) {
String s=strings[0];
try {
URL url=new URL(s);
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
int size=conn.getContentLength();//获取文件大小
//0 标记表示需要更新最大进度值,1 表示更新当前下载的进度值
publishProgress(0,size);
byte[] bytes=new byte[20];
int len=-1;
InputStream in=conn.getInputStream();
FileOutputStream out=new FileOutputStream("/storage/emulated/0/Download/"+System.currentTimeMillis()+".jpg");
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
publishProgress(1,len);//更新进度
out.flush();
}
out.close();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return 200;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
switch (values[0]){
case 0:
activity.progressBar.setMax(values[1]);
break;
case 1:
activity.progressBar.incrementProgressBy(values[1]);
break;
}
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
if (integer==200){
activity.info.setText("下载完成");
}
}
}
}
4.AsyncTask准则
- AsyncTask的实例必须在UI Tread中创建。
- execute方法必须在UI Tread中调用。
- 不要手动的调用onPreExecute()、doInBackground(Params…)、onPostExecute(Result)、onProgressUpdate(Progress…)这几个方法
- 该Task只能被执行一次,否则多次调用时将会出现异常。
- AsyncTask不能完全去掉线程,在一些逻辑较为复杂或者需要在后台反复执行的逻辑就可能需要线程来实现。