什么是AsyncTask
定义:处理异步消息的一个异步类
含义 :为一个轻量级的异步类,与Handler作用相似,不同的是不需要建造子线程主线程
Handler的调用过程:
1. UI线程创建Handler
2. 启动子线程,执行耗时操作
3. 向主线程发送消息
4. handlerMessage接收消息
AsyncTask的执行过程:
1. 新建UI线程,启动AsyncTask
2. 执行耗时消息
3. 接收消息
AsyncTask的泛型参数和常用方法:
- Params:启动任务执行的输入参数
- Progress:后台任务执行的百分比
- Result:后台执行任务最终返回的结果
AsyncTask的常用方法:
- onPreExecute方法:运行在主线程中,最先调用此方法
- doInBackgroud:执行完运行在子线程中,执行耗时操作
- onProgeessUpate方法:显示当前进度,运行在主线程中,需使用publishProgress
- publishProgress:用于触发onProgeessUpate
onPostExecute:当异步任务执行完成后,调用此方法,运行在主线程中
execute:启动异步任务,必须在UI线程中调用,按照先后顺序执行多个
- executeOnExecutor:启动异步任务,必须在UI线程中调用,并行任务同时执行多个任务,最多只能并行5个
如何使用AsyncTask
使用AsyncTask步骤:
1. 新建内部类继承AsyncTask
2. 定义AsyncTask的三种泛型参数
3. 重写doInBackground抽象方法
4. 重写onPreExecute/onProgressUpdate/onPostExecute方法
5. 在需要启动的地方调用execute方法
不带进度的AsyncTask方法的调用顺序:
1. 定义AsyncTask String、int
2. 在UI线程中启动AsyncTask
3. 可初始化控件
4. 执行耗时操作
5. 根据Result设置控件
带进度的AsyncTask的调用顺序:
1. 定义AsyncTask
2. 在UI线程中启动AsyncTask
3. 可初始化
4. 执行耗时操作
使用ASyncTask做倒计时(附代码)
附视图代码
<EditText
android:id="@+id/time_et"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/time_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/daojishi_btn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="带进度AsyncTask倒计时"/>
步骤:
1. 绑定ID, 监听按钮
2. 创建一个类继承AsyncTask,写三个类型方法,实现方法 //耗时操作执行前,对UI的更改
3. onPreExecute方法(主线程),更新时间 //耗时操作执行前,调用此方法,可初始化控件,可省略
4. doInBackgroud方法(子线程),设置倒计时循环,返回计时结束//执行耗时操作
5. onProgressUpdate方法(主线程),显示更新时间//更新当前进度
5. onPostExecute方法(主线程),返回更新按钮//耗时操作执行完成后,调用此方法
代码演示
public class MainActivity extends AppCompatActivity {
private EditText timeet;
private TextView timetv;
private Button daojishibtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindID();
daojishibtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int time=Integer.parseInt(timeet.getText().toString());//把int类型转换成String类型
new MyTask().execute(time);//修改文字框内容
}
});
}
private void bindID() {
timeet=findViewById(R.id.time_et);
timetv=findViewById(R.id.time_tv);
daojishibtn=findViewById(R.id.daojishi_btn);
}
class MyTask extends AsyncTask<Integer,Integer,String>{
//倒计时循环
@Override
protected String doInBackground(Integer... Integer) {
for(int i=Integer[0];i>0;i--){
try{
Thread.sleep(1000);
publishProgress(i);//调用onProgressUpdate方法
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "计时结束";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
timetv.setText("倒计时:"+values[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
daojishibtn.setText(s);//结果回传更新
}
}
}
使用AsyncTask做进度条(附代码)
附视图代码
<ProgressBar
android:id="@+id/pb1"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100" />
<ProgressBar
android:id="@+id/pb2"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100" />
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="开始下载"/>
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="开始下载"/>
步骤:
1. 绑定ID,监听按钮,设置进度条最大值
2. 使用switch语句,选择判断按下了哪个按钮
3. 创建MyTask方法继承ASyncTask,写三个类型方法
4. doInBackground方法,使用for方法进行进度更新,定义一个任意数,返回任意数
5. onProgressUpdae方法,定义两个进度条更新
6. onPostExecute方法,使用swtich方法定义选择对应的按钮更新“下载完成”
代码演示:
public class Jindutiao extends AppCompatActivity implements View.OnClickListener{
private Button btn1;
private Button btn2;
private ProgressBar pb1;
private ProgressBar pb2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jindutiao);
bindID();
}
private void bindID() {
btn1=findViewById(R.id.btn1);
btn2=findViewById(R.id.btn2);
pb1=findViewById(R.id.pb1);
pb2=findViewById(R.id.pb2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
pb1.setMax(10);//设置最大值
pb2.setMax(10);//设置最大值
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1:
btn1.setEnabled(false);
btn1.setText("正在下载");
new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,1);//改成并行
break;
case R.id.btn2:
btn2.setEnabled(false);
btn2.setText("正在下载");
new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,2);//改成并行
break;
}
}
class MyTask extends AsyncTask<Integer,Integer,Integer>{
@Override
protected Integer doInBackground(Integer... integers) {
int whichpb=integers[0];//定义一个任意数
for(int i=1;i<=10;i++){
try {
Thread.sleep(1000);
publishProgress(i,whichpb);//添加任意数
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return whichpb;//返回至任意一个数
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//定义两个进度条进行
switch (values[1]){
case 1:
pb1.setProgress(values[0]);
break;
case 2:
pb2.setProgress(values[0]);
break;
}
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
//定义选择两个下载按钮
switch (integer){
case 1:
btn1.setText("下载完成");
btn1.setEnabled(true);
break;
case 2:
btn2.setText("下载完成");
btn2.setEnabled(true);
break;
}
}
}
}
Execute()和executeOnExecutor有何区别
- execute:启动异步任务,必须在UI线程中调用,按照先后顺序执行多个
- executeOnExecutor:启动异步任务,必须在UI线程中调用,并行任务同时执行多个任务,最多只能并行5个
一般execute运行后想要修改成executeOnExecutor,直接在监听判断按钮时,新建的方法改为executeOnExecutor运行
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1:
btn1.setEnabled(false);
btn1.setText("正在下载");
new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,1);//改成并行
break;
case R.id.btn2:
btn2.setEnabled(false);
btn2.setText("正在下载");
new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,2);//改成并行
break;
}
}
更喜欢ASyncTask还是更喜欢Handler,为什么?
相对于我本人而言,我个人更喜欢ASyncTask
- 首先秉着后来者居上的一个微妙想法,Handler我在大一的时候就已经接触了,当时就对此留下了一定的印象,等到现在接触AsyncTask就相对惊艳了
- 其次Handler每次都需要启动子线程发送消息,handlerMessage接收消息,相对于ASyncTask不需要定义子线程主线程,显得尤其累赘
- 最后虽然AsyncTask每次都需要重复的定义三四个方法,但是只是一个形式,不同的视图使用的都是不同的方法代码,显得尤其的思路清晰,逻辑分明