Handler任务模型之Looper类分析

1. 介绍
上一节完成了对Message类的分析,在Handler消息模型中,Message类是对消息的封装体,本节要介绍的是Looper类,该类的作用是循环询问MessageQueue是否还有要执行的消息,然后将获取到的消息分发出去。

2. 源码分析
首先看下Looper类几个重要的属性信息

 private static final ThreadLocal sThreadLocal = new ThreadLocal();

    final MessageQueue mQueue;
    Thread mThread;
    private static Looper mMainLooper = null;

其中sThreadLocal 代表当前线程的ThreadLocal,mQueue代表该Looper关联的MessageQueue(一个Looper仅有一个MessageQueue关联),mThread代表当前的线程,mMainLooper代表UI线程的Looper
其中Looper的文档介绍这样构建一个新的Handler消息处理模型。

class LooperThread extends Thread {
  *      public Handler mHandler;
  *      
  *      public void run() {
  *          Looper.prepare();
  *          
  *          mHandler = new Handler() {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *          
  *          Looper.loop();
  *      }
  *  }

所以我们首先看下Looper.prepare()方法

  public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

第2行:从ThreadLocal尝试取Looper对象,如果不为空,就会抛出运行时异常,因为一个线程直接对应一个Looper对象,也就是prepare方法也只能被调用一次。这里通过Looper空构造创建的对象

 private Looper() {
        mQueue = new MessageQueue();
        mRun = true;
        mThread = Thread.currentThread();
    }

其中主线程的mainLooper是通过prepareMainLooper方法定义的,内部也是调用Looper.prepare()方法完成Looper初始化操作,另外给myLooper起名为mainLooper而已。

 public static final void prepareMainLooper() {
        prepare();
        setMainLooper(myLooper());
        if (Process.supportsProcesses()) {
            myLooper().mQueue.mQuitAllowed = false;
        }
    }

这样对Looper类属性进行赋值
接下来看Looper.loop()方法的定义

public static final void loop() {
        Looper me = myLooper();
        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();

        while (true) {
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.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("Looper", "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();
            }
        }
    }

我们可以看出10行-42行是一个while(true)死循环,一直调用MessageQueue的next方法获取消息,该方法当没有消息的时候会处于阻塞状态。当取到消息的时候就会通过24行msg.target.dispatchMessage(msg)回调到我们在Handler的callBack或者handleMessage()方法中的代码逻辑。
另外Looper类中比较重要的方法是quit方法

public void quit() {
        Message msg = Message.obtain();
        // NOTE: By enqueueing directly into the message queue, the
        // message is left with a null target.  This is how we know it is
        // a quit message.
        mQueue.enqueueMessage(msg, 0);
    }

note注释中也有说明,一般来说发送一个Message的动作是由一个Handler类完成的,这样一个Message对象就能对应一个Handler对象,此处没有通过handler而是将Message直接添加到MessageQueue消息链表中,会被作为Looper停止的一个标志位,这点会在MessageQueue源码分析中说明。

3. 结束语
通过Looper类的分析,可以看出Looper类的主要作用是循环取消息和分发消息,关于Message的逻辑结构此类是不关心的,关于Message的逻辑结构是在MessageQueue这个类中定义的,下一节将对MessageQueue类进行分析!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值