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

简介: IdleHandler 是 Handler 提供的一种充分利用CPU的机制, 主要是在 MessageQueue 出现空闲的时候被执行
关于作者: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
    }
}

相关文章
|
存储 消息中间件 缓存
相比游戏客户端,游戏服务端开发无关紧要吗
感觉游戏服务端,除了更新,保存数据啊、生成随机物品啊、都没什么了,好像游戏开发场景中,服务端已经无关紧要了。看着客户端忙成狗,正在摸鱼的你是否也有过这样的疑问?
574 0
相比游戏客户端,游戏服务端开发无关紧要吗
|
20天前
|
移动开发 前端开发 API
探索移动开发的未来:跨平台框架与原生性能的平衡
随着智能手机的普及,移动应用成为人们日常生活的重要组成部分。开发者面临一个核心问题:如何高效地构建既兼容多平台又具备高性能的应用程序。本文将探讨跨平台框架和原生开发的优势、挑战及未来趋势,并分析如何在两者之间找到平衡点以适应不断变化的移动市场。
26 1
|
2月前
|
缓存 监控 算法
构建高性能Java应用的秘诀
构建高性能Java应用的秘诀
|
3月前
|
安全 Java 开发者
深入理解Java并发编程:线程安全与性能优化移动应用开发的未来:跨平台框架与原生操作系统的融合
【5月更文挑战第29天】在Java开发中,并发编程是一个重要的议题。随着多核处理器的普及,如何充分利用多核资源,提高程序的执行效率,同时保证数据的安全性和一致性,成为开发者必须面对的挑战。本文将从线程安全的基本概念出发,探讨Java中的线程安全问题,并介绍一些常见的解决方案,如同步机制、锁优化等。最后,我们将通过实例分析,展示如何在保证线程安全的前提下,进行性能优化。
|
3月前
|
存储 缓存 算法
深入理解操作系统内存管理:分页系统的优势与挑战构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第27天】 在现代计算机系统中,内存管理是操作系统的核心功能之一。分页系统作为一种内存管理技术,通过将物理内存划分为固定大小的单元——页面,为每个运行的程序提供独立的虚拟地址空间。这种机制不仅提高了内存的使用效率,还为多任务环境提供了必要的隔离性。然而,分页系统的实现也带来了一系列的挑战,包括页面置换算法的选择、内存抖动问题以及TLB(Translation Lookaside Buffer)的管理等。本文旨在探讨分页系统的原理、优势及其面临的挑战,并通过分析现有解决方案,提出可能的改进措施。
|
3月前
|
存储 缓存 数据库
构建高效Android应用:内存优化策略深度剖析
【4月更文挑战第29天】 在移动开发领域,性能一直是衡量应用质量的关键指标之一。特别是对于Android平台,由于设备硬件配置的多样性,内存管理成为开发者面临的一大挑战。本文将深入探讨Android应用内存优化的有效策略,旨在帮助开发者提升应用性能,减少内存消耗,避免常见的内存泄漏问题。通过对Android内存管理机制的分析与实际案例的结合,我们将提供一系列实用的优化技巧,助力应用在竞争激烈的市场中脱颖而出。
|
3月前
|
缓存 前端开发 Android开发
构建高效Android应用:从设计原则到性能优化
随着移动设备成为我们日常生活不可或缺的一部分,开发一个流畅且响应迅速的Android应用变得至关重要。本文将探讨如何通过遵循Android设计原则和实施细致的性能优化策略来构建高效的Android应用程序。我们将深入分析应用架构的选择、内存管理的要点以及UI设计的优化,旨在为开发人员提供一套实用的指导方针,帮助他们提升应用的整体性能和用户体验。
|
3月前
|
移动开发 监控 Linux
构建高效安卓应用:内存优化实战指南
【4月更文挑战第11天】 在移动开发领域,尤其是安卓平台,内存管理是决定应用性能和用户体验的关键因素之一。本文将深入探讨安卓应用内存优化的策略与实践,从内存分配的基本机制到实际的代码级优化技巧,旨在帮助开发者构建更加高效、稳定且响应迅速的应用程序。通过分析内存泄漏的成因、内存抖动的影响以及合理的内存回收策略,我们展示了如何系统性地解决内存问题,确保应用在各种设备上均能保持最佳性能。
|
3月前
|
机器学习/深度学习 存储 并行计算
YOLOv8改进 | 2023 | AKConv轻量级架构下的高效检测(既轻量又提点)
YOLOv8改进 | 2023 | AKConv轻量级架构下的高效检测(既轻量又提点)
233 0
|
异构计算
《OpenACC并行程序设计:性能优化实践指南》一 3.8 优化GPU内核
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第3章,第3.8节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1040 0