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

简介: IdleHandler 是 Handler 提供的一种充分利用CPU的机制, 主要是在 MessageQueue 出现空闲的时候被执行

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

@TOC

在这里插入图片描述

一、导读

我们继续总结学习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
    }
}

相关文章
|
6天前
|
缓存 移动开发 Android开发
构建高效Android应用:内存优化实战指南
【4月更文挑战第25天】 在移动开发领域,应用程序的性能至关重要。特别是对于Android设备,由于硬件配置的多样性,合理的内存管理与优化是提升应用流畅度、减少卡顿和崩溃的关键。本文将深入探讨Android应用的内存优化技巧,通过分析内存泄漏的原因、诊断工具的运用以及实际代码层面的改进措施,帮助开发者构建更加高效的Android应用。
|
6天前
|
移动开发 监控 Linux
构建高效安卓应用:内存优化实战指南
【4月更文挑战第11天】 在移动开发领域,尤其是安卓平台,内存管理是决定应用性能和用户体验的关键因素之一。本文将深入探讨安卓应用内存优化的策略与实践,从内存分配的基本机制到实际的代码级优化技巧,旨在帮助开发者构建更加高效、稳定且响应迅速的应用程序。通过分析内存泄漏的成因、内存抖动的影响以及合理的内存回收策略,我们展示了如何系统性地解决内存问题,确保应用在各种设备上均能保持最佳性能。
|
6天前
|
监控 Java 测试技术
Java并发编程最佳实践:设计高性能的多线程系统
【4月更文挑战第6天】本文探讨了设计高性能Java多线程系统的关键原则和策略,包括理解并发基础、最小化共享状态、使用高级并发API、避免死锁、利用原子操作、优化锁策略、使用线程池以及监控和调优。遵循这些最佳实践可提升并发性能和可靠性,确保代码健壮性。同时,强调测试并发代码的重要性,以发现和解决潜在问题。
|
7月前
|
运维 监控 Java
03-揭秘大厂性能方案的奥秘!(下)
03-揭秘大厂性能方案的奥秘!
43 0
|
7月前
|
运维 监控 架构师
03-揭秘大厂性能方案的奥秘!(上)
03-揭秘大厂性能方案的奥秘!
52 0
|
10月前
|
存储 SQL 缓存
提升性能的利器:理解线程池的使用、工作原理和优势
在Java中,创建和销毁线程开销较大,为了避免线程过多而带来使用上的开销。 所以我们需要对线程进行统一管理及复用,这就是我们要说的线程池。
|
缓存 Java 编译器
多线程基础——构建高并发应用必会
java多线程编程技术快速学习,经验总结
1020 0
|
测试技术 异构计算
《OpenACC并行程序设计:性能优化实践指南》一 导读
这是一本关于并行编程的书,不仅仅介绍OpenACC语法或从文档中收集的信息,更介绍了如何编写实际的、高性能的以及可移植的程序,这些程序可以运行在从CPU到GPU的大量设备上。具体而言,书中演示了使用PGI、Cray和PathScale等供应商提供的编译器编译示例代码,并在Intel x86处理器、Cavium 96核64位ARMv8处理器芯片集和NVIDIA GPU上运行。
2204 0
|
并行计算
《OpenACC并行程序设计:性能优化实践指南》一 3.11 小结
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第3章,第3.11节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1084 0
|
测试技术 程序员 C++
《OpenACC并行程序设计:性能优化实践指南》一 第2章 性能导向开发
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第2章,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1132 0