在Android中,UI线程不能执行耗时操作的,否则可能会出现ARN。而在工作线程中是不能更新UI的,否则程序会抛出异常。这样,我们就需要在工作线程中执行完耗时操作后来通知UI线程更新UI。这个时候就可以使用Handler。
Handler的简单用法
通常我们使用Handler会在Activity里面新建一个类继承Handler,并重写它的handleMessage()方法。然后在声明的时候直接初始化,或者是在onCreate()中初始化Handler的实例。
class MainActivity : AppCompatActivity() {
private lateinit var btn: Button
private val handler = MyHandler()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initViews()
}
private fun initViews() {
btn = findViewById(R.id.btn)
btn.setOnClickListener {
Thread(Runnable {
//子线程模拟耗时操作
Thread.sleep(3000L)
//耗时操作完成通知UI线程
handler.sendEmptyMessage(0)
}).start()
}
}
inner class MyHandler : Handler() {
override fun handleMessage(msg: Message) {
//更新UI
}
}
}
Handler机制几个比较相关的类
Handler 主要用于创建消息,发送消息,处理消息,删除消息
Looper 在该类内部维护了一个MessageQueue(消息队列),Handler发送的消息会发送到这个消息队列里
MessageQueue 消息队列
Message 消息
Handler
我们首先来看看我们使用Handler时常用的构造方法(Hanlder还有别的构造方法)
public Handler() {
this(null, false);
}
public Handler(@Nullable Callback callback, boolean async) {
...
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
在上面构造方法中,主要是分别为mLooper,mQueue,mCallback这三个属性赋值。其中mLooper赋值为当前线程保存Looper对象。mQueue赋值为当前线程保存的Looper对象的MessageQueue,mCallback在这里被赋值为null。
首先来看一下为mLooper属性数值的Looper.myLooper()方法: