AsyncTask 使用
参考:
AsyncTask:https://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask
是一个轻量级的线程框架,封装了 Thread
和 Handler
的执行细节,方便使用。
AsyncTask
是一个抽象类,需要继承使用
AsyncTask
有3个泛型类型参数:Params
,Progress
和 Result
,以及四个基本的步骤:onPreExecute
,doInBackground
,onProgressUpdate
和 onPostExecute
。
其子类必须 重载至少一个方法 (doInBackground(Params...)
- 这个是抽象方法 ),通常也会重载另一个方法(onPostExecute(Result)
)。
下面介绍一下3个泛型参数的含义:
Params
:发送给后台执行任务的参数类型(the type of the parameters sent to the task upon execution);Progress
:后台计算过程中的进度单位类型(the type of the progress units published during the background computation);Result
:后台计算结果类型(the type of the result of the background computation)。
注:如果不使用参数,可以用 void
代替,比如:
private class MyTask extends AsyncTask<Void, Void, Void> {...}
以及四个基本步骤(其执行顺序从上到下):
onPreExecute()
:在任务被执行时在 UI线程 调用。这个方法通常用于任务执行前的一些工作,比如显示一个进度条;doInBackground(Params...)
:当onPreExecute()
结束后调用,运行在 后台线程 中,计算的任务应该放在这个方法中运行。参数Params
会被输入到这个方法中,同时,该方法计算得出的结果将会作为参数Result
输入到OnPostExecute(Result)
中 。如果在这个方法中调用publishProgress(Progress...)
方法,则会同步调用函数onProgressUpdate(Progress...)
;onProgressUpdate(Progress...)
:在 UI线程 中执行,当onInBackground(Params...)
中调用了函数publishProgress(Progress...)
,才会同步调用这个函数,可以用于显示后台线程的计算进度;onPostExecute(Result)
:在 UI线程 中调用,当后台任务结束后执行。后台任务计算的结果会作为参数输入到这个。
主要内容:
实现四个基本方法
简单工程:显示方法的执行顺序
MyTask.java
代码:
package com.uniview.asynctasktest;
import android.os.AsyncTask;
import android.util.Log;
import java.util.Arrays;
/**
* Created by Lenovo on 2017/3/1.
*/
public class MyTask extends AsyncTask<Void, Integer, Void> {
private static final String TAG = MyTask.class.getSimpleName();
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.e(TAG, "onPreExecute: ");
}
@Override
protected Void doInBackground(Void... params) {
Log.e(TAG, "doInBackground: ");
int values[] = new int[]{1, 2, 3, 4, 5};
for (int i = 0; i < values.length; i++) {
Integer[] temp = new Integer[5];
temp[i] = Integer.valueOf(values[i]);
publishProgress(temp);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
Log.e(TAG, "onProgressUpdate: ");
super.onProgressUpdate(values);
Log.e(TAG, "onProgressUpdate: values = " + Arrays.toString(values));
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Log.e(TAG, "onPostExecute: ");
}
}
MainActivity.java
代码:
package com.example.asynctasktest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Task().execute();
}
}
运行结果如下:
如何取消任务
使用函数 task.cancel(true);
可以取消该任务
如果使用此函数,task
将结束 doInbackground
函数,然后调用 onCancelled()
函数
想要查询是否任务已取消,可以使用方法 isCancelled()
运行规则
AsyncTask
类必须在UI
线程内加载;- 任务实例必须在
UI
线程内创建; - 必须在
UI
线程内执行任务; - 不需要手动调用
onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...)
; - 一个任务实例仅能被执行一次,如果再次执行,将会抛出异常。
多线程的执行顺序
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
最开始的多个 AsyncTask
将会按顺序执行; 从 android 1.6
开始,多线程池将会并行运行,但这可能会造成一些错误;从 android 3.0
开始,多个 AsyncTask
任务将重新按顺序执行,以防止应用错误。
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
如果你想要并行执行,可以调用函数 executeOnExecutor
修改 MyTask.java
:
package com.uniview.asynctasktest;
import android.os.AsyncTask;
import android.util.Log;
import java.util.Arrays;
/**
* Created by Lenovo on 2017/3/1.
*/
public class MyTask extends AsyncTask<Void, Integer, Void> {
private static final String TAG = MyTask.class.getSimpleName();
@Override
protected Void doInBackground(Void... params) {
Log.e(TAG, "doInBackground: ");
int values[] = new int[]{1, 2, 3};
for (int i = 0; i < values.length; i++) {
Integer[] temp = new Integer[3];
temp[i] = Integer.valueOf(values[i]);
publishProgress(temp);
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
Log.e(TAG, "onProgressUpdate: ");
super.onProgressUpdate(values);
Log.e(TAG, "onProgressUpdate: values = " + Arrays.toString(values));
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Log.e(TAG, "onPostExecute: ");
}
}
修改 MainActivity.java
为 按顺序执行 线程:
package com.uniview.asynctasktest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyTask task = new MyTask();
MyTask task2 = new MyTask();
task.execute();
task2.execute();
// task.executeOnExecutor(THREAD_POOL_EXECUTOR);
// task2.executeOnExecutor(THREAD_POOL_EXECUTOR);
}
}
运行结果:
修改 MainActivity.java
为 同步执行 线程:
...
// task.execute();
// task2.execute();
task.executeOnExecutor(THREAD_POOL_EXECUTOR);
task2.executeOnExecutor(THREAD_POOL_EXECUTOR);
...
运行结果: