Android Looper 类

Looper类的重要字段

字段汇总

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class

    final MessageQueue mQueue;
    final Thread mThread;</span>

ThreadLocal 静态引用 :存储当前线程的Looper对象

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

Looper引用 :静态持有主线程的Looper对象

private static Looper sMainLooper;  // guarded by Looper.class

MessageQueue 引用 :当前Looper对象的消息队列

final MessageQueue mQueue;
  1. final修饰,表示当前Looper最多只能有一个消息对象对象

Thread引用 :记录创建当前Looper对象所在的线程

final Thread mThread;

Looper类的重要方法

私有的构造器

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

  1. 创建了 MessageQueue
  2. 记录创建当前Looper对象所在的线程引用
  3. 构造器私有,需要调用其他方法创建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));
    }

  1. 静态方法prepare进行创建Looper对象
  2. 创建Looper对象之后,存储在线程私有数据ThreadLocal中
  3. 对于已经创建过Looper对象的线程,再进行prepare,会引起崩溃。从代码层面,一个线程只能有一个Looper对象。崩溃信息为 "Only one Looper may be created per thread"

主线程 : 主线程的创建不同于子线程

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

  1. main looper由android系统创建
  2. app 开发者永远不需要自己去调用此方法,调用此方法会抛出异常。崩溃信息为 "The main Looper has already been prepared."

启动loop循环

    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;
            }


            final long traceTag = me.mTraceTag;
            if (traceTag != 0) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }

            。。。省略代码

            msg.recycleUnchecked();
        }
    }
  1. loop为静态方法
  2. 调用loop之前没有调用prepare,会抛出异常,提示 “No Looper; Looper.prepare() wasn't called on this thread.”
  3. loop方法的核心是一个for的死循环
  4. loop循环主要做了三件事:
    • 从消息队列中取出消息
    • dispatch message
    • recycle message
  5. loop的终止条件是消息队列没有了消息

Quits Looper

quit

    /**
     * Quits the looper.
     * <p>
     * Causes the {@link #loop} method to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @see #quitSafely
     */
    public void quit() {
        mQueue.quit(false);
    }

  1. 调用此方法后,不再处理post message 请求,如 sendMessage 会返回false
  2. 调用此方法,已经等待的消息执行将终止
  3. 如果想保证等待状态的消息处理完成,需要使用quitSafely

quitSafely

    /**
     * Quits the looper safely.
     * <p>
     * Causes the {@link #loop} method to terminate as soon as all remaining messages
     * in the message queue that are already due to be delivered have been handled.
     * However pending delayed messages with due times in the future will not be
     * delivered before the loop terminates.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p>
     */
    public void quitSafely() {
        mQueue.quit(true);
    }
  1. 当剩余的消息处理完毕之后,立即停止looper
  2. 消息处理完之前,loop不会停止

一些其他方法

获取创建此looper的线程引用

    /**
     * Gets the Thread associated with this Looper.
     *
     * @return The looper's thread.
     */
    public @NonNull Thread getThread() {
        return mThread;
    }

获取此looper的消息队列

    /**
     * Gets this looper's message queue.
     *
     * @return The looper's message queue.
     */
    public @NonNull MessageQueue getQueue() {
        return mQueue;
    }

获取主线程looper对象

    /**
     * Returns the application's main looper, which lives in the main thread of the application.
     */
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值