一.什么是AsyncTask?
Android中,如果想要在子线程里进行UI操作,就需要借助异步消息处理机制,在Android中实现异步任务机制有两种方式,Handler和AsyncTask。Handler在上一篇文章已简单讲述,这里讲述AsyncTask的使用。AsyncTask相对于Handle,代码较为简单,使用更便捷,也可以准确控制子线程。
AsyncTask使用步骤:
- 新建内部类继承AsyncTask;
- 定义AsyncTask的三种泛型参数;
- 重写doInBackground抽象方法;
- 重写onPreExecute抽象方法;
- 重写onProgressUpdate方法;
- 重写onPostEcecute方法;
- 在需要启动的地方调用execute方法。
有三个泛型参数:
三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型“。class DownloadTask extends AsyncTask<Integer, Integer, String>
AsyncTask执行步骤:
1.execute(Params… params),调用此方法,启动子线程。execute方法必须在UI线程中调用,同时启动多个任务时,将按照先后顺序逐一执行比较:executeOnExecutor必须在UI线程中调用,使用executeOnExecutor方法可以并行执行多个任务,但最多也只能是5个任务同时执行
2.onPreExecute(),在execute(Params… params)被调用后立即执行,此方法运行在主线程中,可对控件进行初始化设置,当然这个方法可省略。
3.doInBackground(Params… params),在onPreExecute()完成后立即执行,此方法运行在子线程中,执行费时操作,可以接收输入参数和返回计算结果。注意,这个方法不可以省略
4.onProgressUpdate(Progress… values),在调用publishProgress(Progress… values)时,此方法被执行,直接将进度信息更新到UI组件。
5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上
二.如何使用AsyncTask
带进度AsyncTask方法调用步骤:
1.定义AsyncTask
class MyTask extends AsyncTask<Integer,Integer,String>
2.在UI线程中启动AsyncTask
3.可初始化控件new MyTask().execute()
4.执行耗时操作protected void onPreExecute() { }
5.根据String设置控件protected String doInBackground(Integer... integers) { return null; }
protected void onPostExecute(String s) { }
不带进度AsyncTask方法调用步骤:
1.定义AsyncTask
class MyTask extends AsyncTask<Integer,Integer,String>
2.在UI线程中启动AsyncTask
new MyTask().execute()
3.可初始化控件
protected void onPreExecute() { }
4.执行耗时操作
protected String doInBackground(Integer... integers) { return null; }
5.得到进度设置控件进度
protected void onProgressUpdate(Integer... values) { }
6.根据Result设置控件
protected void onPostExecute(String s) { }
三.使用AsyncTask做倒计时
1.xml布局简单,附上代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/daojishi_ed"
android:layout_width="match_parent"
android:layout_height="50dp" />
<TextView
android:id="@+id/daojishi_tv"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="0"
android:textSize="30sp"
android:gravity="center"/>
<Button
android:id="@+id/daojishi_btn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="开始倒计时"/>
</LinearLayout>
还有xml预览图
2.首先贴上完整的Java代码,下面再进行具体描述:
public class ASdaojishiActivity extends AppCompatActivity {
private TextView daojishiTV;
private Button daojishiBtn;
private EditText daojishiEdit;
int time;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asdaojishi);
bindID();
daojishiBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
time = Integer.parseInt(daojishiEdit.getText().toString());
daojishiBtn.setText("正在倒计时");
new MyAsyncTask().execute(time);
}
});
}
private void bindID() {
daojishiTV = findViewById(R.id.daojishi_tv);
daojishiBtn = findViewById(R.id.daojishi_btn);
daojishiEdit = findViewById(R.id.daojishi_ed);
}
class MyAsyncTask extends AsyncTask<Integer,Integer,String>{
@Override
protected String doInBackground(Integer... integers) {
for (int i = integers[0]; i >= 0; i--){
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "倒计时结束";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
daojishiTV.setText(values[0]+"");
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
daojishiBtn.setText(s);
}
}
}
3.首先需要一个内部类
class MyAsyncTask extends AsyncTask<Integer,Integer,String>
doInBackground方法必不可少,在其内部执行耗时操作
@Override
protected String doInBackground(Integer... integers) {
for (int i = integers[0]; i >= 0; i--){
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "倒计时结束";
}
这里还需要用到两种方法,onProgressUpdate和onPostExecute
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
daojishiTV.setText(values[0]+"");
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
daojishiBtn.setText(s);
}
当然,启动AsyncTask不能缺少
new MyAsyncTask().execute(time);
publishProgress(i);//此行代码对应下面onProgressUpdate方法
return "倒计时结束";//return的String类型数值,给到onPostExecute内的参数
四.使用AsyncTask做进度条
1.xml布局简单,附上代码:
还有xml预览图
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ProgressBar
android:id="@+id/jindutiao_bar"
android:layout_width="match_parent"
android:layout_height="50dp"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
<Button
android:id="@+id/download_btn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="点击下载"/>
</LinearLayout>
2.首先贴上完整的Java代码,下面再进行具体描述:
3.首先需要一个内部类
public class ASjindutiaoActivity extends AppCompatActivity {
private ProgressBar Bar;
private Button downloadBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asjindutiao);
bindID();
downloadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
downloadBtn.setText("正在下载");
new MyTask().execute();
}
});
}
private void bindID() {
Bar = findViewById(R.id.jindutiao_bar);
downloadBtn = findViewById(R.id.download_btn);
Bar.setMax(5);
}
class MyTask extends AsyncTask<Integer,Integer,String>{
@Override
protected String doInBackground(Integer... integers) {
for (int i = 1;i <= 5;i++){
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "下载完成";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Bar.setProgress(values[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
downloadBtn.setText(s);
}
}
}
doInBackground方法必不可少,在其内部执行耗时操作class MyTask extends AsyncTask<Integer,Integer,String>
这里还需要用到两种方法,onProgressUpdate和onPostExecute
@Override
protected String doInBackground(Integer... integers) {
for (int i = 1;i <= 5;i++){
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "下载完成";
}
当然,启动AsyncTask不能缺少
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Bar.setProgress(values[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
downloadBtn.setText(s);
}
}
new MyTask().execute();
publishProgress(i);//此行代码对应下面onProgressUpdate方法
return "倒计时结束";//return的String类型数值,给到onPostExecute内的参数
五.Execute()和executeOnExecutor有何区别
Execute():这个函数让任务是以单线程队列方式或线程池队列方式运行,会让任务以后台单线程串行方式执行。
executeOnExecutor():这个方法通常和THREAD_POOL_EXECUTOR一起使用,允许多个任务在由AsyncTask管理的线程池中并行执行。
AsyncTask实现的原理和适用的优缺点
AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
使用的优点:
简单,快捷
过程可控
使用的缺点:
在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.
Handler异步实现的原理和适用的优缺点
在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)运行并生成Message-Looper获取Message并传递给HandlerHandler逐个获取Looper中的Message,并进行UI变更。
使用的优点:
结构清晰,功能定义明确
对于多个后台任务时,简单,清晰
使用的缺点:
在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)