深入了解IdleHandler,用来做优化或者轻量级任务都是极好的

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

在这里插入图片描述

一、导读

我们继续总结学习Android 基础知识,温故知新。

二、概览

IdleHandler 是 Handler 提供的一种充分利用CPU的机制, 主要是在 MessageQueue 出现空闲的时候被执行,
运行在Looper 所在的线程中,队列出现空闲存在两种场景:

  • 循环拿到的Message为空
  • 这个Message是一个延时的消息;

另外由于IdleHandler 的处理时机不可控,如果 MessageQueue 一直有待处理的消息,那么 IdleHander 的执行时机会很靠后,
所以需要根据具体业务来决定是否使用这样的延迟加载。

三、使用

使用起来非常简单,几行代码即可

    protected void initIdleHandler() {
        MessageQueue.IdleHandler() idleHandler = new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                // TODO: 2023/7/21  
                return true; 当消息队列内没有需要立即执行的消息时,都会触发该方法
                return false;即只会执行一次;
            }
        };
        Looper.myQueue().addIdleHandler(idleHandler);
    }

    手动移除
    Looper.myQueue().removeIdleHandler(idleHandler);
        

3.1 使用场景

主要用于在消息队列空闲的时候处理一些轻量级的工作,
在不影响其他任务,在消息队列空闲状态下执行,如加载图片,延迟初始化,Android Framework层的GC 等

四、原理

IdleHandler看起来好像是个Handler,但他其实只是一个有单方法的接口,是MessageQueue静态内部接口。

    返回值为 false,即只会执行一次;
    返回值为 true,即每次当消息队列内没有需要立即执行的消息时,都会触发该方法。

    public static interface IdleHandler {
        /**
         * Called when the message queue has run out of messages and will now
         * wait for more.  
         * Return true to keep your idle handler active, 
         * false
         * to have it removed.  
         * 
         */
        boolean queueIdle();
    }

在MessageQueue中有一个List存储了IdleHandler对象,当MessageQueue没有需要被执行的MessageQueue时就会遍历回调所有的IdleHandler。
其处理逻辑在 MessageQueue.java 的next方法中,如下:

Message next() {
    ......
    死循环
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }
        //1.阻塞函数
        nativePollOnce(ptr, nextPollTimeoutMillis);
        //2.从链表里面取出消息
        ......
            //3.开始处理IdelHandler
            if (pendingIdleHandlerCount < 0
                    && (mMessages == null || now < mMessages.when)) {
                pendingIdleHandlerCount = mIdleHandlers.size();
            }
            if (pendingIdleHandlerCount <= 0) {
                // No idle handlers to run.  Loop and wait some more.
                mBlocked = true;
                continue;
            }

            if (mPendingIdleHandlers == null) {
                mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
            }
            mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
        }


        // 执行IdleHandler队列中的空闲任务
        for (int i = 0; i < pendingIdleHandlerCount; i++) {
            final IdleHandler idler = mPendingIdleHandlers[i];
            try {
                keep = idler.queueIdle();
            } catch (Throwable t) {
            }
            
            //4.如果keep为false,则就从列表当中去除
            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }
        

        ...
    }
}

如果循环拿到的Message为空,或者这个Message是一个延时的消息,也即当前没有可执行Message,则认为是一个空闲,
这时就开始遍历mIdleHandlers数组, 使用临时数组来保存当前要执行的消息,循环中从数组中取出 IdleHandler,并调用其 queueIdle() 方法。

其流程也并不复杂,我借用一张网络图
在这里插入图片描述

public void addIdleHandler(@NonNull IdleHandler handler) {
    if (handler == null) {
        throw new NullPointerException("Can't add a null IdleHandler");
    }
    synchronized (this) {
        mIdleHandlers.add(handler);       //mIdleHandlers是一个ArrayList
    }
}

五、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

  • 103
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 185
    评论
Java中,HandlerAndroid应用程序开发中常用的一个类,它用于在不同的线程之间进行通信和处理消息。Handler类位于android.os包中,它允许您发送和处理消息和Runnable对象。 在引用\[1\]中的代码片段中,可以看到Instrumentation类中的waitForIdleSync()方法使用Handler来等待消息队列中的消息处理完毕。具体来说,它创建了一个Idler对象,并将其添加到消息队列的IdleHandler中,然后通过Handler的post()方法发送了一个空的Runnable对象,最后调用Idler的waitForIdle()方法等待消息队列为空。 在引用\[2\]中的代码片段中,可以看到ActivityManagerService类中的UiHandler类继承自Handler,并重写了handleMessage()方法。在该方法中,根据收到的消息类型进行相应的处理,比如处理ANR(Application Not Responding)UI消息,并确保系统已经启动完成。 在引用\[3\]中的代码片段中,可以看到在framework中还有其他地方使用IdleHandler。例如,在scheduleGcIdler()方法中,通过调用Looper.myQueue().addIdleHandler()方法将GcIdler对象添加到消息队列的IdleHandler中,以便在消息队列为空闲时执行垃圾回收操作。 总结起来,HandlerJava中是用于处理消息和Runnable对象的类,它可以在不同的线程之间进行通信。在Android开发中,Handler常用于在主线程和后台线程之间进行消息传递和处理。 #### 引用[.reference_title] - *1* *2* *3* [深入理解 Handlerjava 层 + native 层)](https://blog.csdn.net/ldxlz224/article/details/128982717)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android西红柿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值