我们能在主线程直接使用handler,是因为主线程为我们准备好了Looper,并且开启了循环,这样我们在主线程new了Handler之后,就可以使用Handler机制去处理消息了。
但是你直接new了个子线程,想在子线程使用Handler在子线程处理消息,是不行的,你要自己Looper.prepare(),Looper.loop(),才可以。
而HandlerThread这个Thread已经在其run方法里,直接为你准备好了looper,并开启了loop,像是在主线程里那样,你可以直接使用handler了
注意的是,要先开启start()方法,不然的话报错
详解请见
Android HandlerThread 完全解析
package com.mine.threadpooldemo;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView mTvServiceInfo;
private HandlerThread mHandlerThread;
private static final int MSG_UPDATE_INFO = 0x110;
//与UI线程管理的handler
private Handler mHandler = new Handler();
//子线程handler
private Handler mThreadHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTvServiceInfo = (TextView) findViewById(R.id.tv);
//创建后台线程
initBackThread();
}
private void initBackThread() {
// 开启了mHandlerThread,他是一个子线程,
// 里面的run方法里带有一个无限循环的looper
mHandlerThread = new HandlerThread("handler");
// 必须先start,否则报错,因为start后会执行Run方法,run方法里绑定了looper
mHandlerThread.start();
// 得到mHandlerThread里的looper
Looper looper = mHandlerThread.getLooper();
// new一个handler,与mHandlerThread的looper绑定,
// 那么这个handler就是子线程的handler了,
// 这个handler里的handleMessage可以处理耗时任务了
mThreadHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
changeText();
// 发一条空消息,通知mThreadHandler的handlerMessage去执行,开启循环迭代模式
mThreadHandler.sendEmptyMessageDelayed(MSG_UPDATE_INFO, 1000);
}
};
}
@Override
protected void onResume() {
super.onResume();
// 在onCreate里创建好了子线程的handler,并且开启了循环Looper,
// 现在只要用mThreadHandler发消息,就会触发handleMessage去处理消息(在子线程处理哟)
// ★别忘了发消息,否则不执行handleMessage
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
/**
* 模拟一个耗时任务
*/
private void changeText() {
try {
Thread.sleep(1000);
// 注意这个mHandler是在主线程new,所以他使用的是子线程的looper可以操作UI
// 在哪一个线程new handler(),那么这个handler就与哪一个线程绑定
// 当然你使用new Handler(Looper looper)的话,你的handler是与Looper所在的线程绑定在一起的
// 然后,老生常谈mHandler.post(runnable),不一定执行在子线程,而是执行在mhandler所在的线程
// 这里实在主线程,所以可以更改UI
mHandler.post(new Runnable() {
@Override
public void run() {
double randomsdds = Math.random();
mTvServiceInfo.setText(randomsdds + "");
}
});
} catch (InterruptedException e) {
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 释放资源
mHandlerThread.quit();
}
}