前言
在Android中我们可以通过Thread+Handler实现多线程通信,同时我们还可以通过AsyncTask来实现多线程通信,而AsyncTask内部封装了Thread和Handler,可以让我们在后台进行计算并且把计算的结果及时更新到UI上,是Android提供的轻量级的异步类。
一、什么是AsyncTask?
- AsyncTask是Android提供的轻量级(实现代码量少)的异步类;
- 为了降低异步通信的开发难度,提供了AsyncTask;
- AsyncTask直接继承于Object类,位于android.os包中;
使用AsyncTask可以忽略Looper、Message、Hanlder等复杂对象,更便捷的完成异步耗时操作。
说到底AsyncTask的使用是为了方便我们从事Android开发的程序员的使用。
AsyncTask与Hanlder操作过程的比较
Hanlder的调用过程:
UI线程——>创建Hanlder——>启动子线程——>执行耗时操作——>子线程中发送Message——>handlerMessage中接受消息
AsyncTask的执行过程:
UI线程——>启动AsyncTask——>执行耗时操作——>接受消息
通过两个方法的比较,我们可以清晰的看到AsyncTask方法明显比Hanlder方法少了启动子线程这一步操作,这并不是AsyncTask方法不启用子线程操作,而是后台程序已经自动开启了子线程的操作,并不需要AsyncTask方法再次启用。
二、使用AsyncTask的步骤
- 新建内部类继承AsyncTask;
- 定义AsyncTask的三种泛型参数;
- 重写doInBackground抽象方法;
- 重写onPreExecute方法;
- 重写onProgressUpdate方法;
- 重写onPostExecute方法;
- 在需要启动的地方调用execute方法。
三、AsyncTask的泛型参数和常用方法
AsyncTask的三种泛型参数
Params: 启动执行任务的输入参数
Progress:后台任务执行的百分比
Result:后台执行任务最终返回的结果
下面的代码则是内部类继承AsyncTask三种泛型参数的示例代码
class MyTask extends AsyncTask<Params, Progress, Result>
AsyncTask的常用方法
onPreExecute方法:异步任务执行时,系统最先调用此方法;此方法运行在主线程中,可以对控件进行初始化等操作。
doInBackground方法:执行完onPreExecute方法后,系统执行此方法;此方法运行在子线程中,比较耗时的操作放在此方法中执行。
onProgressUpdate方法:在调用publishProgress时,此方法被执行,直接将进度信息更新到UI组件上,此方法的触发,需要在doInBackground中使用publishProgress方法。
onPostExecute方法:当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
execute方法:启动异步任务,调用此方法后,AsyncTask中的方法会被系统逐一调用。
方法的调用顺序以及内部调用的参数:
四、使用AsyncTask方法做倒计时与进度条代码
倒计时:
public class AT2Activity extends AppCompatActivity {
//定义倒计时中的方法
private Button countBtn;
private TextView downTxt;
private EditText countEdit;
private int num;//定义一个整型变量
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_at2);
bindID();//绑定ID
//设置监听事件
countBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//将字符串转换成整型
num=Integer.parseInt(countEdit.getText().toString());
//初始化AsyncTask内部类
MyTask mt = new MyTask();
//启动异步任务
mt.execute(num);
}
});
}
//创建内部类继承AsyncTask方法
class MyTask extends AsyncTask<Integer, Integer, String>{
@Override
protected String doInBackground(Integer... integers) {
int start=integers[0];
int result=0;
for (int i=start;i>=0;i--){
try {
//调用publishProgress方法传值给onProgressUpdate方法
publishProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = i;
publishProgress(result);
}
return result+"";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//更改文本
downTxt.setText(values[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
downTxt.setText(s+"");
}
}
private void bindID() {
countBtn=findViewById(R.id.count_btn);
downTxt=findViewById(R.id.down_text);
countEdit=findViewById(R.id.count_edit);
}
}
进度条:
xml文件中需要加入ProgressBar控件
<ProgressBar
android:id="@+id/progress_bar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"//更改进度的形态
android:layout_width="match_parent"
android:layout_height="60dp" />
Activity方法:
public class ATActivity extends AppCompatActivity {
//定义控件
private Button downloadBtn;
private TextView downloadText;
private ProgressBar downloadBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_at);
bindID();//绑定ID
//设置监听事件
downloadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//初始化AsyncTask内部类
Mytask mt = new Mytask();
//启动异步任务
mt.execute(1000);
}
});
}
//绑定ID的类
private void bindID() {
downloadBtn = findViewById(R.id.doswnload_btn);
downloadText = findViewById(R.id.download_text);
downloadBar=findViewById(R.id.progress_bar);
}
public class Mytask extends AsyncTask<Integer, Integer, String> {
//耗时操作执行前,调用此方法
@Override
protected void onPreExecute() {
super.onPreExecute();
downloadText.setText("正在下载");
}
//执行耗时操作
@Override
protected String doInBackground(Integer... Integer) {//...代表参数个数是不确定的
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(Integer[0]);
publishProgress(i);//更新进度
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "下载完成";
}
//耗时操作完成后,调用此方法
@Override
protected void onPostExecute(String s) {
downloadText.setText(s);
super.onPostExecute(s);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
downloadBar.setProgress(values[0]);
}
}
}
五、execute()与executeOnExecute()的区别
在AsyncTask方法中有多线程任务,而execute()与executeOnExecute()方法就是AsyncTask运行多线程的启动方法
execute()方法是串行的方法,就像下载东西,多个任务一起下载时,只能下载完一个接着下载另一个。
executeOnExecute()方法是并行方法,可以多个任务一起进行,但最多只能五个。
具体实例请观看下面博客
http://blog.youkuaiyun.com/jasper_success/article/details/52291439
根据上篇博客Android——Handler方法与这篇Android——AsyncTask方法的使用相对比,我更喜欢AsyncTask方法,因为这样会更节省代码,虽说执行多线程任务不能像Handler中控制多个线程还有运用灵活,但是AsyncTask更为简单,快捷。