前言
第一次写文章,记录下自己新手Android路上的开发点滴,之前学过AsyncTask基本使用,记录一下,要不然老是忘记。如有发现不对的地方也请多多指教。
正文
AsyncTask是什么?
AsyncTask就是异步处理的任务,它是Handler加上线程池的封装类,线程池可以维护数量,主要是可以避免不必要的创建和开销,AsyncTask必须要在实例的主线程中创建,它的回调方法,Android也会自动的去调用,注意的是,一个AsyncTask的实例,只能调用一次的excute方法。
AsyncTask的基本使用
首先AsyncTask是一个抽象类,用于被继承,而且要指定3个泛型参数,也可以3个都指定为空。
public class MyAsyncTask extends AsyncTask<Params,Progress,Result> {
@Override
protected Void doInBackground(Void... voids) {
return null;
}
}
//Parm:启动任务时输入参数的类型
//Progress:后台任务执行中返回的进度值
//Result:后台执行完成后返回结果的类型
构建 AsyncTaskd子类的回调方法。
-
doInBackground()
:必须重写,异步执行后台线程将要完成的任务。 -
onPreExecute()
:执行后台耗时操作前被调用,一般用来完成用户一些初始化操作。 -
onPostExecute()
:当doInBackground方法完成后,系统会自动调用,并且会将doInBackground返回的值传递给该方法。 -
onProgressUpdate()
:在doInBackground方法调用publishProgress方法后,更新任务的执行进度后,就会触发该方法。
代码如下:
package com.ju.synctask;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.io.InputStream;
import java.net.URLConnection;
/**
* 项目名: SyncTask
* 包名 com.ju.synctask
* 文件名: ImageTest
* 创建日期:2019/4/1
* 描述:图片加载测试类
*/
public class ImageTest extends AppCompatActivity {
private static final String URL = "https://bmob-cdn-23214.b0.upaiyun.com/2019/03/30/9b72512c409fc6bd806acb50a7e7c748.jpg";
private ImageView iv;
private ProgressBar bar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
iv = findViewById(R.id.iv);
bar = findViewById(R.id.pro);
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute(URL);
}
private class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... strings) {
//取出相应的参数值
String url = strings[0];
Bitmap bitmap = null;
URLConnection connection;
InputStream is;
try {
connection = new URL(url).openConnection();
is = connection.getInputStream();//获取输入流
BufferedInputStream bis = new BufferedInputStream(is);
bitmap = BitmapFactory.decodeStream(bis);//将输入流解析成bitmap
bis.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
//初始化
bar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//获取doInBackground的返回值,最后进行处理
iv.setImageBitmap(bitmap);
bar.setVisibility(View.GONE);
}
}
}
模拟进度条测试
package com.ju.synctask;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ProgressBar;
public class PBActivity extends AppCompatActivity {
private ProgressBar bar;
PAsyncTask pAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pbactiviity);
bar = findViewById(R.id.progress);
pAsyncTask = new PAsyncTask();
pAsyncTask.execute();
}
private class PAsyncTask extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... voids) {
//通过for循环模拟进度条进度
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
bar.setProgress(values[0]);
}
}
}
但是你这样做发现了一个问题,如果点击返回的话然后再次进入会发现进度条不动了,这其实是因为上一次的进度条任务没有完成,AsyncTask的任务要进行排队,那要怎么解决了,很简单,可以让AsyncTask和Activity的生命周期保持一次。
在Activity的声明周期添加上这个
@Override
protected void onPause() {
super.onPause();
if (pAsyncTask != null && pAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
pAsyncTask.cancel(true);
}
}
再一次跑起来,发现没什么卵用啊。其实,我们通过调用cancel调用的时候,并没有吧AsyncTask的线程给停止掉,我们只是给这个AsyncTask发送了一个cancel的请求,标记为cancel的状态而已。并不是真正的取消线程执行。我们需要在doInBackground()
和onProgressUpdate()
添加一个isCancelled()
判断,来进行停止AsyncTask,这样就可以停止掉了。
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (isCancelled()) {
return;
}
bar.setProgress(values[0]);
}
总结
AsyncTask的基本使用方法就到此为止了,需要注意的一点是AsyncTask必须要在UI线程也就是主线程中进行创建,也必须在UI线程中调用excute方法,重写的那四个方法是自动调用的。每个AsyncTask只能被执行一次,多次调用有可能会出现异常。也不能在doInBackground()
方法里面更新UI,一定要在onProgressUpdate里进行更新才行。