android消息处理机制

几个概念的介绍:

Looper:Handler和MessageQueue之间的桥梁。系统会为主线程(UI线程)创建一个Looper对象,就是说对于主线程可以直接使用Looper对象,实际上主线程的工作就是不断的从其Looper对象的消息队列中取出消息并执行。系统并没有为子线程创建Looper对象,如果子线程要使用Looper对象必须先创建,有两种创建方式:

public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
从prepare方法的定义中可以看出,prepare方法就是将Looper对象放到ThreadLocal<Looper>中,ThreadLocal会为每一个访问其中保存的变量的线程创建一个变量的副本,每一个线程对该变量的访问都是独立的。(具体怎么实现的,还有点纠结)。这两个方法的返回值都为void,他们只是为当前线程关联一个Looper对象。还有一点要注意的是,Looper类是final型的,也就是说无法通过继承创建自己的Looper类。loop()方法用于循环取出消息队列中的消息,并进行处理,quit()方法结束循环。

public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg); //重点

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();
        }
    }
myLooper()方法返回与当前线程关联的Looper对象,里面有好多代码不太懂,但是最重要的一句话msg.target.dispatchMessage(msg);可以看出loop()方法会将消息队列中取出的消息交给消息中的Handler对象来处理,这也就是为什么说Looper是Handler和MessageQueue之间的桥梁。调用Message的recycle()方法会将处理完的Message对象释放到系统的线程池中。


Message:用于描述各种数据,换句话说,Message对象可以用来存放各种类型的数据这里的数据是要交由Handler中的handleMessage方法来处理的。Message有几个重要的成员变量:Handler、Bundle(键值对的形式携带数据)、Runnable,arg1、arg2用来携带int类型的数据,what用于标记是哪个Message。Object用来携带对象。关于Message对象的实例化系统提供了new Message()方法,但是考虑到效率和内存,推荐使用Handler.obtainMessage(),这个方法还有几个接收不同类型参数的重载方法,都是用来在创建Message对象的时候为Message对象中的成员变量赋值,具体内容可以看API,这里就不说了。


MessageQueue:顾名思义,消息队列,被封装到Looper中,具体怎么工作的不用管,只需要知道他是以队列的方式来存储消息的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值