1、定义
Handler
是Android SDK中的一个类,它允许你发送和处理Message
和Runnable
对象与一个线程的MessageQueue
关联。它主要用于两大功能:
- 调度消息和运行在特定线程上的任务:通过使用
Handler
,你可以将任务排队到该Handler
所关联的线程的消息队列中,任务可以是立即执行的,也可以是延迟一段时间执行的。- 在不同线程之间进行通信:
Handler
允许你从一个线程向另一个线程发送消息,这是一种线程间通信(inter-thread communication)的机制。这通常用于在后台线程完成工作后更新UI(因为UI更新只能在主线程进行)。
2、举例说明
example 1
定时更新UI元素。这个例子展示了Handler控制线程延迟一段时间执行任务的功能。假设你正在开发一个应用,需要在UI上显示一个计时器,计时器每秒钟更新一次。你可以使用
Handler
来实现这个功能。代码如下:
public class MyActivity extends Activity {
private int secondsElapsed = 0;
private TextView timerTextView;
private Handler handler = new Handler();
private Runnable updateTimer = new Runnable() {
@Override
public void run() {
secondsElapsed++;
timerTextView.setText("Seconds Elapsed: " + secondsElapsed);//过了几秒
handler.postDelayed(this, 1000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
timerTextView = findViewById(R.id.timer_text_view);
handler.postDelayed(updateTimer, 1000);
}
}
这边Handler
的作用是确保Runnable
对象每一秒执行一次,以此来更新UI元素(比如显示一个计时器)。这是通过Handler
的postDelayed(Runnable, long)
方法实现的,该方法允许将一个Runnable
任务延迟指定的时间后执行。
example 2
在后台线程处理任务,然后更新UI。假设你需要在后台线程中执行一个耗时的任务,比如从网络下载数据,完成后需要更新UI显示下载的数据,即不同线程的通信功能。
public class MyActivity extends Activity {
private TextView statusTextView;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
statusTextView = findViewById(R.id.status_text_view);
new Thread(new Runnable() {
@Override
public void run() {
// 模拟耗时任务,比如下载文件
downloadFile();
// 下载完成后,使用Handler更新UI
handler.post(new Runnable() {
@Override
public void run() {
statusTextView.setText("Download complete!");//下载完成
}
});
}
}).start();
}
private void downloadFile() {
// 这里模拟下载文件的耗时操作
try {
Thread.sleep(5000); // 模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这边解释一下handler.post(new Runnable()部分代码,post(Runnable)方法,这个方法将一个
Runnable
任务加入到Handler
所关联的线程的消息队列中。这边Handler是在主线程创建的Handler
实例。因为它是在主线程创建的,所以它默认绑定到了主线程的消息队列和Looper
。在这个例子中,Runnable
的run
方法包含更新UI组件的代码。通过这种方式,我们实现了从一个后台线程向主线程(UI线程)发送一个任务的目的。这是因为直接从非UI线程更新UI组件是不允许的,会导致异常。使用
Handler
可以确保UI更新的代码在主线程上安全执行。