上篇文章学习了 Thread 和 Runnable 的方式实现异步。
Android 异步学习(一):Thread 和 Runnable
Android 异步学习(二):Handler 和 AsyncTask
这次学习 Handler 和 AsyncTask。先来说明一下 Handler 和 AsyncTask。
AsyncTask
AsyncTask 是由 Android 提供的轻量级异步工具。
- 优点:使用简单,提供过程主要步骤的接口
- 缺点:多个异步同时进行就会复杂
Handler
Handler 通常是通过重载 handlerMessage 方法接收工作线程的消息,内部进行对主线程进行 UI 操作。通过 sendMessage 发送消息。
下面以下载业务为例,分别说明 AsyncTask 和 Handler
AsyncTask
1. 布局文件
定义了一个 button 和 progress bar,负责开始和进度
<Button
android:id="@+id/btn_start"
android:layout_width="160dp"
android:layout_height="60dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_dashboard"
app:layout_constraintEnd_toEndOf="parent"
android:text="Start" />
<ProgressBar
android:id="@+id/pb_down"
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_marginTop="10dp"
android:layout_marginHorizontal="20dp"
android:max="100"
android:progressDrawable="@drawable/progressbar_bg"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
app:layout_constraintTop_toBottomOf="@+id/btn_start"/>
2. DownAsyncTask
public class DownAsyncTask extends AsyncTask<Integer, Integer, String> {
private ProgressBar progressBar;
private Context context;
public DownAsyncTask(Context context, ProgressBar progressBar) {
super();
this.context = context;
this.progressBar = progressBar;
}
// 该方法在后台执行下载的操作
@Override
protected String doInBackground(Integer... integers) {
int i = 0;
for (; i < 101; i++) {
// 通过该方法可以触发onProgressUpdate,从而更新UI
publishProgress(i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 返回值是onPostExecute的参数,可以在onPostExecute中显示进度
return String.valueOf(i);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(context, "开始下载", Toast.LENGTH_SHORT).show();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Toast.makeText(context, "下载完成", Toast.LENGTH_SHORT).show();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// 更新UI
progressBar.setProgress(values[0]);
}
}
3. Activity/Fragment
最后就是使用,在定义的 Button 的 Click 监听中执行 execute 方法就可以了。
DownAsyncTask downAsyncTask = new DownAsyncTask(this, mProgressBar);
downAsyncTask.execute();
- Handler
还是上面的布局文件,Handler 有两种方式进行实现
- 方式一 Post(Runnable)
- 先创建工作线程实现 Runnable 接口,在 run 中进行耗时操作。
- 然后在利用 handler 的 post 方法,在实现 Runnable 接口的 run 方法中更新 UI。
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
new Thread(new Runnable() {
@Override
public void run() {
// TODO下载操作
int i = 0;
for (; i < 101; i++) {
final int finalI = i;
handler.post(new Runnable() {
@Override
public void run() {
// TODO 更新UI
mProgressBar.setProgress(finalI);
}
});
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
break;
-
方式二 Message
- 创建工作线程继承 Thread,重写 run 方法执行耗时操作,在工作线程中通过 handler.sendMessage 方法发送 Message。
- 创建 Handler,重写 handlerMessage 方法,在这里接收工作线程发送的 Message,根据业务执行更新 UI 操作。
class DownThread extends Thread {
@Override
public void run() {
super.run();
int i = 0;
for (; i < 101; i++) {
handler.sendEmptyMessage(i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
new DownThread().start();
handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
// 这里使用msg.what作为进度更新UI
mProgressBar.setProgress(msg.what);
}
};
break;
以上就是 AsyncTask 和 Handler 的基本使用方式。下篇学习 RxAndroid 的使用。