Looper源码细说

Looper作为引擎般的存在,主要作用是维持一个死循环,一旦有消息到来就通知handler分发事件。

Looper的创建

   //线程中初始化 获取Looper 
    public static void prepare() {
        prepare(true);
    }


    private static void prepare(boolean quitAllowed) {
//sThreadLocal 存放线程的局部变量   每个线程拿到一个原始变量的副本进行操作
//在这里就是为每个线程存放一个Looper对象,如果已经存在  则报异常
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
//sThreadLocal 存放线程的局部变量   每个线程拿到一个原始变量的副本进行操作
//多了一个quitAllowed  默认是true  主线程赋值false表示looper不可退出
        sThreadLocal.set(new Looper(quitAllowed));
    }
//主线程初始化Looper的地方  在MainThread的main方法里面调用 这也是主线程里面不用调prepare的原因
    public static void prepareMainLooper() {
        prepare(false);
//下面是主线程多出来的部分  就是单独的为主线程的Looper设置一个线程局部变量sMainLooper 
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
//myLooper()  方法里就一句话 return sThreadLocal.get();  最终拿到线程sThreadLocal
            sMainLooper = myLooper();
        }
    }
....
//上面 进过prepare 最终new一个Looper对象
//同时拿到MessageQueue和创建宿主线程thread;
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

Looper的退出

    public void quit() {
        mQueue.quit(false);
    }

    public void quitSafely() {
        mQueue.quit(true);
    }

上面简短的代码可以看出 其调用的是成员变量MessageQueue的退出方法 那我们就跟进看一看
MessageQueue中的代码


    void quit(boolean safe) {
//mQuitAllowed  主线程调用prepare时传false  不允许在主线程中退出循环 
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }

        synchronized (this) {
            if (mQuitting) {
                return;
            }
            mQuitting = true;
//safe  looper中传入判断是否安全退出
//安全退出则只移除等待传递的消息否则清空所有
            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }

            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }

Looper运作
核心部分

  public static void loop() {
  //拿到Looper对象
        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;
//重置并获取当前线程跟踪令牌 确保线程身份不变
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

//looper维持的无限循环
        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
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
//拿到消息后进行消息分发
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
//事件分发后判断线程身分是否有变
            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.recycleUnchecked();
        }
    }

消息如何出队 下一篇会说下MessageQueue和message

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值