Looper、Message、MessageQueue、Handler归纳总结

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(基础概念)***
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值