在Android中,工作线程是不能直接使用Handler的。要想在工作线程中使用Handler,必须首先在工作线程中创建一个Looper对象并调用Looper.loop()方法。Android系统提供了一个HandlerThread类可以在工作线程中直接使用Hander。
HandlerThread继承自Thread,本身是一个线程。只是在该线程的内部自动为我们创建了Looper对象并调用了Looper.loop()方法。
HandlerThread的简单使用
class MainActivity : AppCompatActivity() {
private lateinit var btn: Button
private val thread = HandlerThread("workThread")
private lateinit var handler:MyHandler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
thread.start()
handler = MyHandler(thread.looper)
initViews()
}
private fun initViews() {
btn = findViewById(R.id.btn)
btn.setOnClickListener {
//从主线程发消息到工作线程
handler.sendEmptyMessage(0)
}
}
override fun onDestroy() {
super.onDestroy()
thread.quit()
}
inner class MyHandler(looper: Looper) : Handler(looper) {
override fun handleMessage(msg: Message) {
//该方法运行在工作线程
//模拟耗时操作
Thread.sleep(3000L)
runOnUiThread {
//更新UI
}
}
}
}
HandlerThread源码
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
...
}
可以看到,在run()方法里面调用了Looper.prepare()和Looper.loop()。接着我们创建Handler的时候使用了getLooper()方法。
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
上面的代码返回的就是在run()方法中创建的Looper对象。不过在run()中为mLooper赋值后使用了notifyAll(),而在上面的getLooper()方法中有一个wait()。造成这种实现的原因是Looper对象是在工作线程中创建的,而我们的Handler却是在主线程中初始化的。因此,我们要确保在获取Looper时已经创建,否则就需要让主线程阻塞等待Looper的创建成功。