多线程—AsyncTask
1 说在头里
开始之前,还是要先逼逼几句。都知道,Android中子线程是不能直接更新UI的,如果想要修改,Android提供了以下集中方式:
- Handler 实现:
- Activity.runOnUiThread(Runnable):
- View.post(Runnable):
- View.postDelayed(Runnable, long):
对于异步任务,安卓提供更更为轻量级的操作方式,那就是今天的主角AsyncTask。这位哥哥是一个抽象类,需要继承,并且在继承时,需要指定3个泛型参数。
2 正题
AsyncTask适用于简单的异步任务,无需借助线程和Handler实现。首先说一下AsyncTask<Params, Progress, Result>三个泛型参数含义:
- Params:用于指定启动任务执行时输入参数的类型
- Progress:后台任务完成进度值的类型
- Result:任务执行完成后返回结果的类型
看不懂说啥呢?没关系,先放着,待会回头看。要使用这个类很简单,废话没有,三步走。
- 创建AsyncTask的子类,并为三个泛型参数指定类型,如果不需要使用,直接给个Void(Void是大写V,小写v会报错)
- 根据任务需求,重写AsyncTask的一些方法,有几个方法需要说明一下:
- doInBackground(Params...): 该方法应该被重新,该方法就是后台要执行的任务。在该方法中可以直接调用publishProgress(Progress... Values)更新任务的执行进度。
- onProgressUpdate(Progress... Values): 该方法在publishProgress(Progress... Values)被调用后被触发执行。
- onPreExecute(): 一般该方法在执行后台任务前被调用,用于完成一些初始化操作,比如UI显示下载进度条。
- onPostExecute(Result result): doInBackground()方法执行完成后,系统会回调该方法,doInBackground()的返回值是该方法的输入参数。
- 在UI线程中创建一个AsyncTask对象,并调用execute()方法。注意,每个AsyncTask只能执行一次,多次执行会抛出异常。
3 举个栗子
使用AsyncTask做一个倒计时,很简单按照上面三步走原则进行实践。
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = findViewById(R.id.show);
}
public void start(View source) {
//第三步在UI线程中创建一个AsyncTask对象,并调用execute()方法
TimerTask task = new TimerTask(this);
task.execute(new Integer(10));
}
//第一步创建一个AsyncTask的子类
class TimerTask extends AsyncTask<Integer, Integer, Void> {
Context mContext;
public TimerTask(Context ctx) {
mContext = ctx;
}
//第二步,实现doInBackground方法,onProgressUpdate方法
@Override
protected Void doInBackground(Integer... params){
int num = params[0].intValue();
while(num > 0){
num--;
publishProgress(new Integer(num));
try {
Thread.sleep(1000);} catch (InterruptedException err) {}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... num) {
int i = num[0].intValue();
if (i >= 0) {
show.setText(num[0].intValue()+" ");
} else {
}
}
}
}
4 最好有个总结
在使用AsyncTask时,要指定这三个泛型参数,三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。
一个异步任务的执行一般包括以下几个步骤:
1.execute(Params… params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2.onPreExecute(),在execute(Params… params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
3.doInBackground(Params… params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress… values)来更新进度信息。
4.onProgressUpdate(Progress… values),在调用publishProgress(Progress… values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
上面五种方法中的参数要与上面自己指定的泛型类型要保持一致。
此部分内容属于转载,转载信息如下
————————————————
版权声明:本文为CSDN博主「csd54496」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/csd54496/article/details/45848405
顺便给一下xml文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="138dp"
android:layout_marginTop="198dp"
android:layout_marginEnd="160dp"
android:layout_marginBottom="78dp"
android:text="10"
android:textSize="100dp"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="57dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="293dp"
android:onClick="start"
android:text="开始"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/show"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>