参考
Handler理解
- Handler一般用于进行线程间通讯,一般是子线程向主线程发送数据变动,更新UI操作。
- Handler的消息回调接收是是跟你创建Handler的线程绑定的,即你在那个线程创建的Handler,其不管在那个线程发送消息,最后回调的方法实现都是在你创建Handler的线程里完成。
- Handler跟Thread没有关系,其内部不能做耗时操作,但是可以发送延迟消息… …
Handler机制
- Message:消息,由MessageQueue统一队列,交给Handler处理。
- MessageQueue:消息队列,用来存放Handler发送过来的Message,并且按照先入先出的规则执行。
- Handler:处理者,负责发送和处理Message.
- Looper:死循环,不断从MessageQueue中获取Message并执行。
Looper
- Handler的创建时该线程中必须含有Looper对象。
- 在程序启动时,系统会先加载ActivityThread这个类,该类在main方法中会生成Looper对象:
Looper.prepareMainLooper()
,并随之创建消息队列,然后会调用Looper.loop()
进行队列中的消息循环,故MainThread中可以直接创建Handler对象,发送消息。 - 非主线程是不自带Looper的,如果在子线程中进行Handler的创建需要自己调用
Looper.prepare()
创建Looper对象,不然会报java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
异常。注意:调用之前需要判断该线程是否有Looper对象,通过:Loopper.myLooper()
来判断,不然会报java.lang.RuntimeException: Only one Looper may be created per thread
异常。 - 获取主线程的Looper对象:
Looper.getMainLooper()
。Handler-Message&Runable
- sendMessage():一般用于线程间消息传递
- post(new Runnable):其并不是开启一个Thread,只是单纯的发送一个Null的消息,回调会在Runnable的实现run()方法只执行,一般会结合HandlerThread来使用。
子线程创建Handler对象(子线程需要借助Looper处理)
- 方式一:
public class MyHandlerThread extends Thread {
public static final String TAG = "MyHT";
public Handler mHandler = null;
@Override
public void run() {
Log.d(TAG, "进入Thread的run");
Looper.prepare();//looper创建
mHandler = new Handler(Looper.myLooper()){
@Override
public void handleMessage(Message msg){
Log.d(TAG, "获得了message");
super.handleMessage(msg);
}
};
Looper.loop();//因开始无限while(true)死循环,下边的代码不会再执行,mHandler.getLooper().quit(),可以结束Looper.loop循环
... ...
//主线程的所有操作都在Looper循环体内部执行,故不会出现这种情况
}
}
方式二(HandlerThread:为创建子线程Looper做了安全封装):
//在MainThread中创建,HandlerThread其实就是在创建个带有Looper对象的子线程 //也不能这样说:其实就是创建了个Looper对象,只是在子线程中创建的Looper对象、、、之所以创建还不是因为Handler需要在子线程中使用 //Handler handler =new Handler();//其实内部参数是需要传入一个Looper对象的
HandlerThread handlerThr=new HandlerThread("HandlerThread");
handlerThr.start();//开启线程
Looper looper = handlerThr.getLooper();
Handler handler=new Handler(looper, new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
//该Handler是在子线程中创建的--所以其handlerMessage()回调仍然在子线程中--回调线程是个创建Handler的线程在一起
//故这个回调里也不能更新UI
//需要handler.sendMessage();才能走改回调
//因为其已经创建过Looper.prepare()<--->Looper.loop(),顾Toast可以show;
Toast.makeText(Main2Activity.this, "异步回调", Toast.LENGTH_SHORT).show();
//Only the original thread that created a view hierarchy can touch its views
//btnHandlerThread.setText("thread");
return false;
}
});//该Handler就是在子线程中生命的Handler---并且 你不需要Looper.prepare();Looper.loop(),HandlerThread内部已经创建了Looper对象;
......... // UI操作
.........
.........
if(handler!=null) {
handler.post(new Runnable() {
@Override
public void run() {
///这个是主线程回调不是子线程-可以更新UI,,message.callBack=runable;\跟普通View.post(new Runable{})不知道有啥区别
btnHandlerThread.setText("main-thread");
Toast.makeText(Main2Activity.this,"异步请求",Toast.LENGTH_SHORT).show();
}
});
}
Destory取消队列循环
- sendMessage()方式进行消息传递:handler.removeCallBacksAndMessages(null)
- post(runnable)方式:handler.removeCallBacks(runnable);