Java多线程之异步任务——AsyncTask

时间:2022-08-29 18:37:01
为什么需要异步任务?
1、Android单线程模型
2、耗时操作放在非主线程中执行

AsyncTask为何而生?
1、子线程中更新UI
2、封装、简化异步操作

构建AsyncTask子类的参数
AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承,继承AsyncTask需要制定如下三个泛型参数:
Params:启动任务是输入参数的类型。
Progress:后台任务执行中返回进度值的类型。
Result:后台执行任务完成后返回结果的类型。


构建AsyncTask子类的回调方法:
doInBackground:
必须重写,异步执行后台线程将要完成的任务;
onPreExecute:执行后台耗时操作前调用,通常用户完成一些初始化操作;
onPostExecute:当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground()方法返回的值传给该方法;
onProgressUpdate:在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,就会触发该方法。

回调方法的执行顺序:
onPreExecute() -> doInBackground() -> onPostExecute()

在doInBackground()方法中调用publishProgress()方法更新任务的执行进度:
onPreExecute() -> doInBackground() -> onProgressUpdate() -> onPostExecute()

完成初始化操作       完成耗时操作              更新进度条                得到doInBackground的返回值进行处理


接下来新建一个Android项目测试一下,新建Android项目之后,直接添加一个MyAsyncTask类:

public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = "MyAsyncTask";

@Override
protected Void doInBackground(Void... arg0) {
Log.e(TAG, "****doInBackground****");
publishProgress();
return null;
}

@Override
protected void onPostExecute(Void result) {
Log.e(TAG, "****onPostExecute****");
super.onPostExecute(result);
}

@Override
protected void onPreExecute() {
Log.e(TAG, "****onPreExecute****");
super.onPreExecute();
}

@Override
protected void onProgressUpdate(Void... values) {
Log.e(TAG, "****onProgressUpdate****");
super.onProgressUpdate(values);
}


}

而后在MainActivity.java里面new一个MyAsyncTask类,并调用execute()方法:

public class MainActivity extends ActionBarActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyAsyncTask task = new MyAsyncTask();
task.execute();
}

}

运行查看Log打印情况:

Java多线程之异步任务——AsyncTask

根据打印的Log,我们可以发现四个方法的运行顺序。

接下来我们修改一下并继续编写项目,简单的使用一下AsyncTask。

MyAsyncTask类:

public class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {
private static final String TAG = "MyAsyncTask";
private ImageView imageView;

public MyAsyncTask(ImageView imageView){
this.imageView = imageView;
}

@Override
protected Bitmap doInBackground(String... arg0) {
Log.e(TAG, "****doInBackground****");
publishProgress();
//获取传递进来的参数
String url = arg0[0];
Bitmap bitmap = null;
URLConnection connection;
InputStream is;

try {
connection = new URL(url).openConnection();
is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
//通过decodeStream解析输入流
bitmap = BitmapFactory.decodeStream(bis);
is.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
//将Bitmap作为返回值
return bitmap;
}

@Override
protected void onPostExecute(Bitmap bitmap) {
Log.e(TAG, "****onPostExecute****");
imageView.setImageBitmap(bitmap);
super.onPostExecute(bitmap);
}

@Override
protected void onPreExecute() {
Log.e(TAG, "****onPreExecute****");
super.onPreExecute();
}

@Override
protected void onProgressUpdate(Void... values) {
Log.e(TAG, "****onProgressUpdate****");
super.onProgressUpdate(values);
}


}


MainActivity类:

public class MainActivity extends ActionBarActivity {
private final String URL = "https://www.baidu.com/img/bd_logo1.png";
private ImageView imageView1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView1);
MyAsyncTask task = new MyAsyncTask(imageView1);
task.execute(URL);
}

}


activity_main.xml布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.itman.asynctaskdemo.MainActivity" >


<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_launcher" />

</RelativeLayout>

别忘记添加网络访问权限,最后运行项目,结果如下图:

Java多线程之异步任务——AsyncTask



异步任务---AsyncTask使用的注意事项:
1、必须在UI线程中创建AsyncTask的实例
2、必须在UI线程中调用AsyncTask的execute()方法
3、重写的四个方法是系统自动调用的,不应手动调用
4、每个AsyncTask只能被执行一次,多次调用将会引发异常(尤其注意