目录:
目录
1. 前言
本篇文章介绍 Android Handler 的基本使用方法,且 Demo 会以 Java & Kotlin 两种代码形式进行展示。
在 Android 实际开发中,我们经常会遇到耗时任务,比如:网络请求API接口来获取数据、数据库 CRUD 操作等等,我们需要额外创建开启工作线程来处理这些耗时任务。由于 Android 规定只能由主线程才能处理 UI 工作,所以这时候我们就需要通过 Handler 来通知主线程处理 UI 工作。
1.1 定义
Handler:子线程与主线程之间的沟通中介,用于传递处理消息。
在 Android 中,为保证处理 UI 工作的线程稳定安全,规定只有主线程才能更新处理 UI 工作。所以当子线程想处理 UI 工作时,就需要通过 Handler 来通知主线程作出相对应的 UI 处理工作。
如下图所示:
Handler是子线程与主线程的沟通中介
本篇文章,我将介绍 Handler 的三种使用方法,分别是:
Handler.sendMessage(Message)
Handler.post(Runnable)
Handler.obtainMessage(what).sendToTarget();
2. Handler.sendMessage()方法
Handler.sendMessage(Msg) 方法是最为常见的一种方法。
2.1 使用步骤说明
其使用步骤分四步,如下所示:
步骤一:新建 Handler 对象,覆写 handleMessage(Message) 方法。
步骤二:新建 Message 对象,设置其携带的数据。
步骤三:在子线程中通过 Handler.sendMessage(Message) 方法发送信息。
步骤四:在 Handler 的 handleMessage(Message msg) 方法中处理消息,通知主线程作出相对应的 UI 工作。
步骤一:新建 Handler 对象,覆写 handleMessage(Message) 方法
//创建 Handler对象,并关联主线程消息队列
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
···略···
}
}
};
步骤二:新建 Message 对象,设置其携带的数据
Bundle bundle = new Bundle();
bundle.putInt(CURRENT_PROCESS_KEY, i);
Message msg = new Message();
msg.setData(bundle);
msg.what = 2;
步骤三:在子线程中通过 Handler.sendMessage(Message) 方法发送信息
mHandler.sendMessage(msg)
步骤四:在 Handler 的 handleMessage(Message msg) 方法中处理消息,通知主线程作出相对应的 UI 工作
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//根据信息编码及数据做出相对应的处理
switch (msg.what) {
case 1:
//更新 TextView UI
mDisplayTv.setText("CustomChildThread starting!");
break;
case 2:
//获取 ProgressBar 的进度,然后显示进度值
Bundle bundle = msg.getData();
int process = bundle.getInt(CURRENT_PROCESS_KEY);
mProgressBar.setProgress(process);
break;
default:
break;
}
}
};
2.2 具体例子
根据上述的使用步骤,我们来完成一个完整的例子:
新建一个线程,模拟处理耗时任务,然后将处理进度通过 ProgressBar 显示出来。
效果如下所示:点击按钮,开启线程处理耗时操作。
Handler.sendMessage() Demo
具体代码见下:
2.2.1 Java版本Demo
Java版本的具体代码如下所示:
public class HandlerAddThreadActivity extends AppCompatActivity {
public static final String CURRENT_PROCESS_KEY = "CURRENT_PROCESS";
private TextView mDisplayTv;
private Handler mHandler;
private ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_add_thread);
TextView titleTv = findViewById(R.id.title_tv);
titleTv.setText("Handler + Thread");
mDisplayTv = findViewById(R.id.display_tv);
mProgressBar = findViewById(R.id.test_handler_progress_bar);
//mHandler用于处理主线程消息队列中的子线程消息
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handl