AsyncTask
封装好的异步消息处理机制
属于抽象类,需要创建子类继承AsyncTask。
开启子线程执行耗时任务,实现子线程和主线程之间的通信,完成主线程的UI更新操作。
优点
- 方便实现异步通信
- 采用线程池的缓存线程和复用线程,避免频繁创建销毁线程带来的系统资源开销。
AsyncTask实现类
public abstract class AsyncTask<Params,Progress,Result>{
}
三个泛型参数的意义:
- Params:开始异步任务执行时传入给后台的的参数类型。
- Progress:任务执行过程中,下载进度显示单位的数据类型。
- Result:异步任务执行完成后,返回的结果类型。
常用方法
execute(Params param)
在主线程中触发执行异步线程任务。
onPreExecute()
在execute()钱自动调用,用处界面初始化操作,比如显示一个进度条对话框。
doInBackground(Params params)
该方法内所有代码都在子线程中运行,处理耗时任务,任务完成通过return语句将任务的执行结果返回,如果AsyncTask
第三个泛型参数是Void,可以不返回任务执行结果。该方法不可以进行UI操作。
onProgressUpdate(Progress values)
后台任务调用publishProgress(Progress)方法后,该方法自动调用,在该方法内可以对UI进行操作。
onPostExcute(Result result)
后台任务执行完毕并通过return语句进行返回是,该方法自动调用。利用返回的数据进行UI操作,比如提醒任务执行的结果,关闭进度条对话框等。
onCancelled()
取消状态并非真正的取消任务,该方法执行后,onPostExecute()方法就不会被调用。
定义子类
private class MyTask extends AsyncTask<Params, Progress, Result> {
@Override
protected void onPreExecute() {
//线程任务前的初始化操作
}
@Override
protected String doInBackground(String... params) {
// 自定义的线程任务
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count);
}
@Override
protected void onProgressUpdate(Integer... progresses) {
// 在主线程 显示线程任务执行的进度
}
@Override
protected void onPostExecute(String result) {
// UI操作
}
@Override
protected void onCancelled() {
}
}
//创建实例
MyTask mTask = new MyTask();
//执行任务
mTask.execute();
举个例子
public class MainActivity extends AppCompatActivity{
private static String TAG = "MainActivity";
private TextView showText;
private Button startButton;
private Button cancelButton;
private ProgressBar progressBar;
private MyTask myTask = new MyTask();
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showText =(TextView)findViewById(R.id.text);
progressBar = (ProgressBar)findViewById(R.id.progress_bar);
startButton = (Button)findViewById(R.id.start_button);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常
myTask.execute();
}
});
cancelButton = (Button)findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myTask.cancel(true);
}
});
}
private class MyTask extends AsyncTask<String,Integer,String> {
@Override
protected void onPreExecute(){
showText.setText("加载中");
}
@Override
protected String doInBackground(String...params){
try{
int count = 0 ;
int length = 1;
while(count<99){
count += length;
//调用publishProgress()显示进度,之后执行onProgressUpdate()
publishProgress(count);
Thread.sleep(50);
}
}catch(InterruptedException e){
e.printStackTrace();
}
return null;
}
// 主线程显示执行进度
@Override
protected void onProgressUpdate(Integer...progresses){
progressBar.setProgress(progresses[0]);
showText.setText("loading...."+progresses[0]+"%");
}
// 任务执行结果
@Override
protected void onPostExecute(String result){
showText.setText("加载完成");
}
//取消加载
@Override
protected void onCancelled(){
showText.setText("取消加载");
progressBar.setProgress(0);
}
}
}
注意点
生命周期
结论
AsyncTask不与任何组件绑定生命周期
使用建议
在Activity 或 Fragment中使用 AsyncTask时,最好在Activity 或 Fragment的onDestory()调用 cancel(boolean);
内存泄漏
结论
若AsyncTask被声明为Activity的非静态内部类,当Activity需销毁时,会因AsyncTask保留对Activity的引用 而导致Activity无法被回收,最终引起内存泄露
使用建议
AsyncTask应被声明为Activity的静态内部类
线程任务执行结果 丢失
结论
当Activity重新创建时(屏幕旋转 / Activity被意外销毁时后恢复),之前运行的AsyncTask(非静态的内部类)持有的之前Activity引用已无效,故复写的onPostExecute()将不生效,即无法更新UI操作
使用建议
在Activity恢复时的对应方法 重启 任务线程