目录
前言
一、AsyncTask简介。
二、AsyncTask和Handler对比
1、AsyncTask实现的原理和适用的优缺点
2、Handler异步实现的原理和适用的优缺点
三、AsyncTask使用方式。
- AsyncTask定义了三种泛型类型 Params、Progress、Result
- 一个异步加载数据最少要重写以下这两个方法
- 有必要的话你还得重写以下这三个方法,但不是必须的
- 使用AsyncTask类,以下是几条必须遵守的准则
四、AsyncTask小实例。
【附录】
Demo
前言
在【异步处理之Handler】中我们已经了解了关于线程的相关知识,明白为什么要进行异步处理以及使用Handler进行异步处理的方式,今天我们就来了解一下异步处理的另一种方式 —— ** AsyncTask。**
一、AsyncTask简介。
Android应用的主线程(UI 线程)肩负着绘制用户界面和及时响应用户操作的重任,为了避免在主线程中做耗时操作而产生的ANR提示,我们就要把耗时的任务移出主线程,交给工作者线程去做。工作者线程主要有AsyncTask、IntentService、HandlerThread,它们本质上都是对线程或线程池的封装。
二、AsyncTask和Handler对比
1、AsyncTask实现的原理和适用的优缺点
-
AsyncTask提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
-
优点:简单快捷 、过程可控。
-
缺点:
-
在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来。
-
只是代码上轻量一些,而实际上要比handler更耗资源。
2、Handler异步实现的原理和适用的优缺点
-
在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)运行并生成Message-Looper获取Message并传递给Handler,Handler逐个获取Looper中的Message,并进行UI变更。
-
优点:结构清晰,功能定义明确,适于处理多个后台任务。
-
缺点: 在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)。
【总的来说为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。】
三、AsyncTask使用方式。
AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法。
- AsyncTask定义了三种泛型类型 Params、Progress、Result
Params :启动任务执行的输入参数,比如HTTP请求的URL。
Progress :后台任务执行的百分比。
Result :后台执行任务最终返回的结果,比如String。
- 一个异步加载数据最少要重写以下这两个方法
doInBackground(Params…)
//后台(非主线程)执行比较耗时的操作,注意这里不能直接操作UI。
//doInBackground在执行过程中可以调用publishProgress(Progress…)来更新任务的进度。
onPostExecute(Result)
//(主线程执行),相当于Handler处理UI的方式,可以使用在doInBackground 得到的结果处理操作UI。
- 有必要的话你还得重写以下这三个方法,但不是必须的
onProgressUpdate(Progress…)
//(主线程执行)可以使用进度条显示任务执行的进度。
onPreExecute()
//(主线程执行)当任务执行之前开始调用此方法,可以在这里显示进度对话框。
onCancelled()
//用户调用取消时,要做的操作。
- 使用AsyncTask类,以下是几条必须遵守的准则
- Task的实例必须在UI thread中创建;
- execute方法必须在UI thread中调用;
- 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
- 该task只能被执行一次,否则多次调用时将会出现异常;
四、AsyncTask小实例。
- 新建一个MyAsyncTask
public class MyAsyncTask extends AsyncTask<String, Integer, String> {
private static final String TAG = "ASYNC_TASK";
//MainActivity的进度条
ProgressBar myprogressbar = null;
//MainActivity的文本
TextView textView = null;
// MainActivity的上下文
Context mycontext = null;
public MyAsyncTask(ProgressBar progressbar, TextView textview, Context context) {
myprogressbar = progressbar;
mycontext = context;
textView = textview;
}
//onPreExecute方法用于在执行后台任务前做一些UI操作
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i(TAG, "onPreExecute() called");
textView.setText("正在加载...");
myprogressbar.setProgress(0);
}
//doInBackground方法内部执行后台任务,不可在此方法内修改UI
//params 由UI线程调用execute()方法传入
//返回的String类型参数被onPostExecute()方法调用。
@Override
protected String doInBackground(String... params) {
Log.i(TAG, "doInBackground(Params... params) called");
String ret = null;
/**
* 通过Begin,End演示多参数传值
*/
String Begin = params[0];//取出值Begin
String End = params[1];//取出值End
Log.i(TAG, "doInBackground" + Begin);
/**
* 模拟耗时步骤
*/
for (int i = 0; i < 10; i++) {
/**
* 后台线程向UI线程发布进度状态i
*/
publishProgress(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(TAG, "doInBackground" + End);
ret = "更新完毕";
return ret;
}
//onPostExecute方法用于在执行完后台任务后更新UI,显示结果
//result为doInBackground()返回的参数
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i(TAG, "onPostExecute(Result result) called");
textView.setText(result);
}
@Override
//onProgressUpdate方法用于更新进度信息
//values为doInBackground()中publishProgress()返回的参数
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.i(TAG, "onProgressUpdate(Progress... progresses) called");
int progress = myprogressbar.getMax() / 10 * (values[0] + 1);
myprogressbar.setProgress(progress);
textView.setText("正在加载..." + progress + "%");
}
//onCancelled方法用于在取消执行中的任务时更改UI
@Override
protected void onCancelled() {
Log.i(TAG, "onCancelled() called");
textView.setText("已被取消");
myprogressbar.setProgress(0);
}
}
- MainActivity
public class MainActivity extends AppCompatActivity {
private ProgressBar myProgressBar;
private Button start, cancel;
private TextView textView;
private MyAsyncTask mTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myProgressBar = (ProgressBar) findViewById(R.id.progressBar);
start = (Button) findViewById(R.id.start);
cancel = (Button) findViewById(R.id.cancel);
textView = (TextView) findViewById(R.id.tv);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//注意每次需new一个实例,新建的任务只能执行一次,否则会出现异常
//启动异步任务,并传入"Begin","End"值演示UI线程向后端线程传值的情况
mTask = new MyAsyncTask(myProgressBar, textView, getApplicationContext());
mTask.execute("Begin", "End");
start.setEnabled(false);
cancel.setEnabled(true);
}
});
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTask.cancel(true);
start.setEnabled(true);
cancel.setEnabled(false);
}
});
}
}
- 效果
-
点击开始
点击开始
-
-
执行完毕
执行完毕 -
打印结果,注意执行顺序
打印结果,注意执行顺序 -
执行取消
取消 -
打印结果
打印结果
【附录】
Demo
整理作者:汪博
少壮不努力,老大徒悲伤。
本文为Android学习规划打造,如有不好的地方请多多指教。
网友评论