欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Looper、Message、MessageQueue、Handler归纳总结

程序员文章站 2022-07-14 17:04:42
...

Message Queue 消息队列

MessageQueue是一个消息队列,用来存放通过Handler发布的消息。消息队列通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到
当前线程的消息队列。如果没有消息队列对象则会抛出空指针异常 。Android在 第一次启动程序时会默认会为UI thread创建一个关联的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等等。你可以在自己的子线程中创建Handler与UI thread通讯。也就是说我们程序一启动我们的UI线程也就是主线程就会有一个消息队列 ,而如果我们自己另外开启的一个子线程就不会有MessageQueue(消息队列)对象。

  Message Queue按照先进先出执行。 每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。

Handler

通过Handler你可以发布或者处理一个消息或者是一个Runnable的 实例。每个Handler都 会与唯一的一个线程以及该线程的消息队列关联。当你创建一个新的Handler时候,默认情况下,它将关联到创建它的这个线程和该线程的消息队列。也就是说,如果你通过Handler发 布消息的话,消息将只会发送到与它关联的这个消息队列,当然也只能处理该消息队列中的消息。这里大家就得理解一下了 也就是说我们 一个Handler对应一个线程以及附属于该线程的消息队列。

Looper Looper是每条线程里的Message Queue的管家。

Looper扮演着一个Handler和 消息队列之间通讯桥梁的角色。程序组件首先通过Handler把 消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。
  Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL,它不会抛空指针异常。Looper类为一个线程开启一个消息循环,里面有一个消息队列,新线程是没有开启消息循环的,所以需要用到Looper的方法创建消息循环(主线程除外,主线程会自动为其创建Looper对象,开启消息循环),MessageQueue存放消息和事件。

对于子线程使用Looper,API Doc提供了正确的使用方法:

package com.test;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
class LooperThread extends Thread { 
    public Handler mHandler; 
    public void run() { 
        Looper.prepare(); //创建本线程的Looper并创建一个MessageQueue
        mHandler = new Handler() { 
            public void handleMessage(Message msg) { 
            // process incoming messages here 
            } 
        }; 
        Looper.loop(); //开始运行Looper,监听Message Queue 
    }     
}
这个Message机制的大概流程:
  1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。
  2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用该Message的target指向的Hander的dispatchMessage函数对Message进行处理。
  在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:
  1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;
  2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;
  3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
  由此可见,我们实现的handleMessage方法是优先级最低的。
  3. Handler处理完该Message (update UI) 后,Looper则设置该Message为NULL,以便回收!


通过分析Activity源码,我们知道每个Activity都有一个Looper,所以主线程在接收Message是不需要调用Looper.prepare()和Looper.loop(),但是非主线程是不带Looper的,当非主线程要接收来自主线程的消息是就需要调用Looper.prepare()和Looper.loop()。

demo1:Looper、Handler应用---实现主线程向子线程发送消息

Looper原型:
Looper.prepare()
Looper.loop
Looper.quit
代码:
package com.test.looper;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class MainActivity extends Activity {
	private LooperThread  looperThread;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        looperThread = new LooperThread();
        looperThread.start();
		looperThread.getHandler().sendEmptyMessage(1);
    }
    
    class LooperThread extends Thread {
        private Handler mHandler;
        private final Object mSync = new Object();

        public void run() {
            Looper.prepare();
            synchronized (mSync) {
                mHandler = new Handler(){
                	@Override
                	public void handleMessage(Message msg) {
                		Log.d("CYQ", "--->" + msg);
                	}
                };
                mSync.notifyAll();
            }
            Looper.loop();
        }
        
        public Handler getHandler() {
            synchronized (mSync) {
                if (mHandler == null) {
                    try {
                        mSync.wait();
                    } catch (InterruptedException e) {
                    }
                }
                return mHandler;
            }
        }
        public void exit() {
            getHandler().post(new Runnable(){
                public void run() {
                    Looper.myLooper().quit();
                }});
        }
    }
}
注意一下几点:

1、new Handler()必须在子线程的run方法中,否则不是子线程的Handler

2、在getHandler方法中,加入同步防止线程start了,但是并没有run结束,若此时直接返回mHandler会是一个null,源码中有更稳定的实现。


参考:

4、http://byandby.iteye.com/blog/825071(基础概念)***