- Handler 、 Looper 、Message
- 整个异步处理消息的流程
- 线程间通信
- Handle是和生成的时候所在的线程绑定的,并和绑定的线程的Looper和MessageQueue绑定;在子线程中通过handle.obtainMessage()生成消息并绑定到主线程的Handle,便可以将子线程中的消息发给主线程的Handle.
Handler 、 Looper 、Message
-
简单的应用:更新progressBar进度条
Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.arg1 > 100) msg.arg1 = 0; progressBar.setProgress(msg.arg1); handler.postDelayed(myThread, 1000); } }; handler.post(myThread); Runnable myThread = new Runnable() { int i = 0; @Override public void run() { Log.e("run", i+""); i += 10; Message msg = handler.obtainMessage(); msg.arg1 = i; if (i == 100) { i = 0; handler.removeCallbacks(myThread); handler.removeMessages(msg.arg1); } handler.sendMessage(msg); } };
-
异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。
-
Looper主要是prepare()和loop()两个方法。
-
Looper主要作用:
- 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
- loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
整个异步处理消息的流程
-
首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
-
Looper.loop()会让当前线程进入一个无限循环,不断从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
-
Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue相关联。
-
Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
-
在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
-
产生一个Message对象,可以new,也可以使用Message.obtain()方法;两者都可以,但是更建议使用obtain方法,因为Message内部维护了一个Message池用于Message的复用,避免使用new 重新分配内存。
Message message = myHandler.obtainMessage(); //获取一个Message对象,并且绑定myHandle Message message = Message.obtain(); //获取一个Message对象,没有绑定handle
线程间通信
//主线程MainActivity中:
myButton01.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() { //开启子线程
@Override
public void run() {
System.out.println("the thread id is "
+ Thread.currentThread().getId());
System.out.println("the thread name is"
+ Thread.currentThread().getName());
/** 定义消息对象 并且赋予内容 最后发送给UI线程
*这里这个方法要说明一下 myHandler.obtainMessage()-->obtainMessage这个方法用来获得消息对象
*但是这个消息对象会关联调用它的Handler对象。所以就会关联myHandler对象 而这个myHandler对象是在UI线程里边创建的
* 所以很显然我们这消息会发给主线程的消息队列 我想这对大家来说根本没有任何难度
*/
Message message = myHandler.obtainMessage();
message.obj = "message";
//把消息发送给目标对象,目标对象就是 myHandler 就是关联我们得到的那个消息对象的Handler
message.sendToTarget();
}
//启动线程
}.start();
}
});
-
Handle是和生成的时候所在的线程绑定的,并和绑定的线程的Looper和MessageQueue绑定;在子线程中通过handle.obtainMessage()生成消息并绑定到主线程的Handle,便可以将子线程中的消息发给主线程的Handle.
结语:
坚持每天进步一点点…