用IdleHandler来性能优化及原理源码分析

Android开发系列:IdleHandler闲时加载 在之前的文章里,我们讲过关于handler的一些使用和原理。今天讲一个系统预留的一个handler,IdleHandler,有了它,可以让我们在系统闲时进行一些预加载或者事务处理。 阅读详情

背景:

经常在做一些app冷启动速度优化等性能优化工作时候,经常可能会发现有时候需要引入一些第三方sdk,或者库,这些库一般会要求我们在onCreate中进行初始化等,但是onCreate属于生命周期的回调方法,如果onCreate中业务过多就会影响整个app的冷启动时长,很多人这个时候第一想到可能是放入子线程等,但是经常又发现有的调用还要求在主线程调用等限制,所以针对这种情况下就经常会使用到一个IdleHandler,这个当初使用时候大家可能就只是字面意思理解为空闲的Handler,在空闲时候执行,其实没有深入去看看它到底实现原理是什么,今天刚好有机会就来给大家进行一个剖析。

IdleHandler 的概念

IdleHandler 是 MessageQueue 提供的一个接口,用于监听消息队列的空闲状态。它允许开发者在主线程处于空闲时,执行一些低优先级的任务。IdleHandler 的核心方法 queueIdle() 会在系统检测到消息队列空闲时调用。返回值决定了 IdleHandler 是否继续在队列中保留:若返回 true,则该回调在下次队列空闲时继续执行;反之,返回 false 则表示仅执行一次后移除。

IdleHandler 和性能优化

IdleHandler 的出现正好迎合了性能优化的需求。在实际开发中,有一些任务并非必须实时完成,例如日志上报、资源预加载、缓存清理、数据统计、一些动画或预渲染任务等。利用 IdleHandler,可以将这些不紧急的任务推迟到主线程消息队列空闲时再执行,从而避免干扰用户看到的实时界面更新,提高整体界面流畅度和响应速度。因此,在 UI 主线程相对繁忙时,通过 IdleHandler 来分摊任务,可以让系统先处理用户的核心交互,就比如onCreate是生命周期方法,如理里面初始化太多东西影响冷启动速度,针对一些可以延后不那么紧急任务可以待系统空闲时再处理任务,充分利用 CPU 空闲时间。

源码分析IdleHandler

为了更加全面了解IdleHandler,下面将要从以下几个部分进行IdleHandler的源码分析。
1、
IdleHandler的接口解释:
frameworks/base/core/java/android/os/MessageQueue.java

    /**
     * Callback interface for discovering when a thread is going to block
     * waiting for more messages.
     */
    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.  This may be called if there are still messages
         * pending in the queue, but they are all scheduled to be dispatched
         * after the current time.
         */
        boolean queueIdle();
    }

上面注释就可以看出来,这个IdleHandler属于一个回调接口,这个接口在线程即将要阻塞等待更多消息时候会被调用。
queueIdle就是对应的回调函数,这个queueIdle有一个返回值true或false,这两个值分别有如下区别:
如果返回true意味着下一次空闲依旧会执行这个IdleHandler的回调函数。
如果返回false就代表当前IdleHandler已经执行完毕,下次空闲不会再执行该IdleHandler。

添加IdleHandler接口

    /**
     * Add a new {@link IdleHandler} to this message queue.  This may be
     * removed automatically for you by returning false from
     * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
     * invoked, or explicitly removing it with {@link #removeIdleHandler}.
     *
     * <p>This method is safe to call from any thread.
     *
     * @param handler The IdleHandler to be added.
     */
    public void addIdleHandler(@NonNull IdleHandler handler) {
        if (handler == null) {
            throw new NullPointerException("Can't add a null IdleHandler");
        }
        synchronized (this) {
           //这里其实就是加入到mIdleHandlers这个集合中
            mIdleHandlers.add(handler);
        }
    }

这里的addIdleHandler添加就是简单加入的mIdleHandlers这个集合中,方便后面执行时候进行遍历

IdleHandler的触发执行

    @UnsupportedAppUsage
    Message next() {
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
           //进入等待消息,要被唤醒2种情况,1被其他函数wake,2等待时间nextPollTimeoutMillis到
            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                //当消息的Handler为空时,则查询异步消息
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                     //当查询到异步消息,则立刻退出循环
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
               	 //检测msg时间是还没到了
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        //还没到msg的处理时间,那么就会与当前时间进行差值,这个差值就是等待时间nextPollTimeoutMillis
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                        //设置下一个消息为mMessages
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        msg.markInUse();
                        //直接return回去消息,也就是有消息都在这里return了不会执行下面业务
                        return msg;
                    }
                } else {
                //没有找到消息
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }

                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                //找了一圈发现没有要处理的消息了,那么就开始判断是否有IdleHandler的消息要处理
                //注意这里的pendingIdleHandlerCount第一次进入才是-1,后续一旦执行IdleHandler都是变成0,不会再进入
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    //把mIdleHandlers集合大小赋值给pendingIdleHandlerCount
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                //如果发现没有IdleHandler,那么就返回循环进行block阻塞等待唤醒
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }
							//如果mPendingIdleHandlers这个数组没有初始化就进行初始化,这里最小大小为4应该是为了性能以防频繁扩容
                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                //mIdleHandlers转成了数组mPendingIdleHandlers
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            //开始正式执行对应的IdleHandler
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                //执行IdleHandler的对应回调业务方法
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }
								//这里的keep就是queueIdle的返回值,如果返回false就会从mIdleHandlers进行移除
                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }
						//把pendingIdleHandlerCount变成0,不是-1,这样防止死循环执行IdleHandler
            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;
					//这里是为了让尽快遍历一下是否有消息,因为可能执行IdleHandler期间有新消息
            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

上面next方法,关于IdleHandler执行总结如下:
1、next方法遍历消息队列,确实没有寻找到要处理的消息任务
2、没有要处理的消息则开始处理IdleHandler相关的任务
3、如果IdleHandler的queueIdle返回false则会从mIdleHandlers删除,下次空闲就不会在执行这个IdleHandler,否则true的话会每次空闲都执行

实战案例

测试一下queueIdle返回false,即只执行一次queueIdle

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        getMainLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                //TODO 执行一些不那么紧急任务                
                Trace.beginSection("queueIdle no next runing");
                Log.i("lsm66666","queueIdle return false,no next runing");
                Trace.endSection();
                return false;
            }
        });
    }

验证结果:
在这里插入图片描述

再测试一下queueIdle返回true,即执行多次queueIdle

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        getMainLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                //TODO 执行一些不那么紧急任务                
                Trace.beginSection("queueIdle has next runing");
                Log.i("lsm66666","queueIdle return true,has next runing");
                Trace.endSection();
							return true;
            }
        });
    }

看看日志打印情况
在这里插入图片描述

systrace结合分析IdleHandler

在这里插入图片描述

上面也可以看出来IdleHandler的执行都在没有消息可以处理了,才会执行,而且执行完成后就进入消息等待时期。
从上面也可以看出来,IdleHandler确实是在主线程空闲暂时没有消息处理时候进行执行的,可以起到一个错峰执行的目的,不过也要注意以下几点:

1、切勿让IdleHandler执行耗时操作,应该是可以快速完成的一些任务

2、尽量都让IdleHandler执行是一次性任务,即queueIdle返回false,以防每次空闲都有重复调用

文章参考:https://mp.weixin.qq.com/s/7R2ws-6oBij3OrNMA_IfTA

更多framework实战开发干货,请关注下面“千里马学框架”

深入理解Android Handler机制:从原理到进阶实战 本文深入解析Android开发中的Handler机制,从基础原理到高级应用。首先介绍Handler四组件(Handler、Message、MessageQueue、Looper)的架构全景,通过源码分析核心工作原理。随后展示基础实战案例,包括跨线程UI更新和定时任务处理,强调主线程Handler的必要性和内存泄漏防范。重点剖析IdleHandler机制,解释其在消息队列空闲时触发的特性,通过源码分析展示其执行流程。文章提供丰富的代码示例,帮助开发者全面掌握这一Android线程通信的核心技术,从基础使用到I 阅读详情

相关推荐

Matrix卡顿优化之IdleHandlerLagTracer源码分析

IdleHandlerLagTracer的实现逻辑还是很简单的,它通过hook的方法替换了主线程消息队列的IdleHandlers集合,从而拦截到了IdleHandler的添加和移除逻辑,在拦截到添加IdleHandler的操作时,为原来的IdleHandler做一层代理,从来可以在queueIdle方法执行时做超时监听逻辑,超时未执行完成则收集信息上报,从而发现IdleHandler导致的卡顿问题。

maniuT的博客 752

IdleHandler 是什么?怎么使用,能解决什么问题?

一. 序 Handler 机制算是 Android 基本功,面试常客。但现在面试,多数已经不会直接让你讲讲 Handler 的机制,Looper 是如何循环的,MessageQueue 是如何管理 Message 等,而是基于场景去提问,看看你对 Handler 机制的掌握是否扎实。 本文就来聊聊 Handler 中的 IdleHandler,这个我们比较少用的功能。它能干什么?怎么使用?有什么合适的使用场景?哪些不是合适的使用场景?在 Android Framework 中有哪些地方用到了它? 二.

Dream It Possible 1万+

基于人脸识别的课堂考勤系统 tkinter+openpyxl+face_recognition

基于face_recognition库实现人脸考勤系统功能。利用Python的tkinter模块来设计考勤系统的图形化界面,此外结合openpyxl模块,实现将学生的信息和考勤打卡数据保存到表格中,方便查看和调用。该系统具备“刷脸打卡”、“新学生注册”等功能。............

lyx4949的博客 6968

Android:IdleHandler的简单理解和使用

IdleHandler 说白了,就是 Handler 机制提供的一种,可以在 Looper 事件循环的过程中,当出现空闲的时候,允许我们执行任务的一种机制。,当然要注意这里执行的代码同样不能太耗时,因为它是同步执行的,如果太耗时肯定会影响后面的 message 执行。MessageQueue 是一个基于消息触发时间的优先级队列,所以队列出现空闲存在两种场景。,也就是当下次队列空闲的时候,不会继续回调它的 queueIdle 方法了。这个获取消息队列下一个待执行消息的方法中,我们跟一下具体的逻辑。

JMW1407的博客 5581

IMU、INS、GNSS与组合导航:从原理到工程实践全解析

在自动驾驶、无人机和机器人等智能系统的定位方案中,IMU、INS、GNSS和组合导航常被混为一谈,但它们在硬件层级、数据特性和误差机制上截然不同。IMU作为惯性测量单元,以百赫兹以上频率输出加速度和角速度;INS基于IMU完成姿态、速度与位置的递推解算,却因积分累积误差而随时间漂移;GNSS提供绝对位置,但易受遮挡和干扰。组合导航通过卡尔曼滤波将两者融合,实现短期不飘、长期不偏的连续定位,这正是高精度导航系统的技术底座。工程落地时,从IMU标定、Allan方差分析到相机/LiDAR与IMU外参标定,再到松耦

weixin_29193259的博客 384

Robocup3d

一、 比赛介绍 RoboCup 仿真比赛是一个能为多智能体系统和模拟智能进行研究、教育的工具。比赛是在一个标准的计算机环境中进行的,提供了一个完全分布式控制、实时异步多智能体环境。通过这个平台,可以测试各种理论、算法和Agent体系结构。在实时异步、有噪声的对抗环境中,研究多智能体的合作对抗问题。当然,仿真组的比赛使用的机器人并非是真的机器人。一个机器人是一个Agent, 它拥有自己的大脑,

zhanghe2775115的专栏 7267

Android IdleHandler 原理解析与应用场景

IdleHandler 是 Android MessageQueue 机制中的一个接口,允许在主线程空闲时执行任务。本文详细解析 IdleHandler 的工作原理,包括 MessageQueue 结构、触发时机及其使用方法。同时,我们探讨了 IdleHandler 的应用场景,如延迟初始化、资源回收和数据预加载等,并分析了其优缺点。合理使用 IdleHandler 可以优化应用性能,提高用户体验。本文将帮助开发者深入理解 IdleHandler 并在实际开发中灵活运用。

帅次的博客 3465

基于JavaEE的银行大客户关系维护系统(JSP+java+springmvc+mysql+MyBatis)

基于JavaEE技术的大型银行客户关系管理系统可以实现客户信息的集中管理、客户需求的分析与挖掘、个性化的服务推荐等功能。+ Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。用户发送请求:用户通过浏览器或其他客户端向系统发送请求,请求访问特定的页面或执行特定的操作。前端展示结果:前端接收到后端返回的数据,根据需要进行展示。数据返回给前端:后端程序处理完业务逻辑后,将结果数据返回给前端。后端程序接收到请求后,根据请求的类型和参数进行相应的处理。

gp1052的博客 719

Android:Handler中的Idle Handler

[Android] Handler中的IdleHandler 抛出 Handler中的IdleHandler 它有什么能力? 它有什么用处? 能想到一些合适的场景吗? Answer1: 首先看下源码的注释 /** * Callback interface for discovering when a thread is going to block * waiting ...

weixin_45136073的博客 1638

MIPS-5级流水线CPU

一、流水线CPU 流水线CPU就是指将一条分解为多步,在同一周期内进行多条指令的同时执行。MIPS五级流水线就是将指令分为:取指(IF),译码(ID),执行(EX),访存(MEM),写回(WB)五个阶段。举个例子: 比如第二条指令lui $t2,0x2100 在流水线CPU中执行的就是 可以看到在200-300ns的周期里,IF阶段取到0x00400004处的指令,300-400ns,这条指令到了ID阶段,而IF阶段执行下一条指令。400-500ns,执行这条指令,ALU的结果为0x2100

weixin_43877853的博客 2万+

ADS 2023 实战:手把手教你仿真一个中心频率 2.4GHz 的带通滤波器(附工程文件)

本文详细介绍了使用ADS 2023软件设计和仿真中心频率2.4GHz带通滤波器的全流程,包括工程准备、指标定义、原理图设计、仿真优化及实际电路实现。通过切比雪夫滤波器拓扑和参数优化,实现高性能的带通滤波器设计,适用于无线通信系统。附有工程文件和常见问题解决方案,助力工程师快速掌握射频滤波器设计技巧。

weixin_30790841的博客 482

IdleHandler的使用和源码解析

1.作用 IdleHandler用于执行耗时较短且非必须的任务,它会在消息队列空闲时执行任务,可以用于性能优化。 2.使用 queueIdle函数返回false的话,这个任务会被执行一次,如果返回true,则消息队列空闲时就执行(注意不是只要空闲了就不断执行,而且空闲后就执行一次) var handler:MessageQueue.IdleHandler = obje...

z979451341的博客 1227

2、探索谷歌云平台(GCP):入门指南

本文全面介绍了谷歌云平台(GCP)的入门知识,涵盖其全球基础设施、核心服务和使用方法。内容包括GCP区域与可用区结构、创建免费账户、配置计算资源(如GCE虚拟机)、存储类型(PD、Filestore、GCS)、网络架构(VPC)、组织与项目管理、身份访问控制(IAM),以及计算、存储、数据库、大数据和人工智能等各类云服务。文章还提供了资源规划、安全管理和成本控制等实用建议,帮助用户快速上手并高效利用GCP构建可扩展的云解决方案。

uber9的博客 255

IdleHandler 的原理分析和妙用,80后程序员月薪30K+感慨中年危机

Message next() { // Return here if the message loop has already quit and been disposed. // This can happen if the application tries to restart a looper after quit // which is not supported. ··· int nextPollTimeoutMillis = 0; for (;???? { if (nextPollTimeou

m0_66264798的博客 176

SAP BW/4HANA 项目字段级数据血缘分析的方法与工具

利用SAP自带工具可以在一定程度上查看数据流和字段使用情况,但往往需要人工逐步深挖。适用于简单场景或验证单个字段的映射。借助SAP数据治理解决方案(如 Information Steward、Data Intelligence 等)能够自动整合元数据,提供图形化、跨系统的血缘分析,适合对数据 lineage 有严格要求的企业级项目。第三方工具则提供了灵活强大的功能,如自动文档、生成功能丰富的报告,对于复杂环境下的血缘分析和影响分析非常有帮助。自行开发SQL/CDS脚本。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 471

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Android Handler 机制完全解析

Android的Handler机制是用于线程间通信的核心组件,主要解决子线程更新UI的问题。其核心包括四个部分:Message(消息对象)、MessageQueue(消息队列)、Looper(循环器)和Handler(处理器)。Handler通过发送Message到MessageQueue,Looper不断从队列中取出消息并由Handler处理,实现线程间通信。使用时需注意内存泄漏问题,推荐采用静态内部类+弱引用方式,并在onDestroy中移除消息。现代开发中可用协程、LiveData等替代方案,但理解H

迷茫的小亮仔的博客 986

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

IdleHandler 原理与使用

IdleHandler是Android消息机制中的一种空闲任务处理机制,当Looper没有消息需要处理时,会执行注册的IdleHandler任务。其使用方式是实现IdleHandler接口的queueIdle()方法,并通过MessageQueue的add/remove方法进行注册和注销。源码分析表明,IdleHandler的执行时机是在MessageQueue空闲时(无消息或消息未到触发时间),通过next()方法中的循环处理所有注册的IdleHandler。如果queueIdle()返回false,该H

似霰的博客 809

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Android IdleHandler 原理浅析

问:什么是 IdleHandler?有什么用?怎么用? 答:IdleHandler 可以用来提升性能,主要用在我们希望能够在当前线程消息队列空闲时做些事情(譬如 UI 线程在显示完成后,如果线程空闲我们就可以提前准备其他内容)的情况下,不过最好不要做耗时操作。具体用法如下。 //getMainLooper().myQueue()或者Looper.myQueue() Looper.myQ...

qijingwang的博客 452

Handler中的IdleHandler

IdleHandler 基本情况 IdleHandler 可以用来提升性能,主要用在我们希望能够在当前线程 消息队列空闲时 做些事情(例如UI线程在显示完成后,如果线程空闲我们就可以提前准备其他内容)的情况下,不过最好不要做耗时操作。 具体用法如下 //getMainLooper().myQueue()或者Looper.myQueue() Looper.myQueue().addIdleHandl...

ruanyandong的博客 573

android idle监听,Android IdleHandler 原理浅析

问:什么是 IdleHandler?有什么用?怎么用?答:IdleHandler 可以用来提升性能,主要用在我们希望能够在当前线程消息队列空闲时做些事情(譬如 UI 线程在显示完成后,如果线程空闲我们就可以提前准备其他内容)的情况下,不过最好不要做耗时操作。具体用法如下。//getMainLooper().myQueue()或者Looper.myQueue()Looper.myQueue().ad...

weixin_34693059的博客 471

(4.1.10.7)Android IdleHandler 原理浅析

问:什么是 IdleHandler?有什么用?怎么用? 答:IdleHandler 可以用来提升性能,主要用在我们希望能够在当前线程消息队列空闲时做些事情(譬如 UI 线程在显示完成后,如果线程空闲我们就可以提前准备其他内容)的情况下,不过最好不要做耗时操作。具体用法如下。 //getMainLooper().myQueue()或者Looper.myQueue() Looper.myQueue().addIdleHandler(new IdleHandler() { @Overrid.

JAVA成长之路 263

IdleHandler 不可以执行耗时操作的原因

是 Android 消息机制中的一部分,通常用于在消息队列空闲时执行一些额外的处理逻辑。为了保证应用的流畅性和稳定性,耗时操作应该放在后台线程中进行,例如使用。

challenge51all的专栏 359

Android百问百答-《那些年被问过的Handler原理》

Android百问百答-《那些年被问过的Handler原理 关于Handler,安卓面试最热门的知识点之一。本篇文章将围绕3点展开: 可以提问哪些Questions? 面试官会怎样follow up? 以及怎样寻找答案。 文章快速索引Android百问百答-《那些年被问过的Handler原理Handler常见提问Handler常见Follow UpHandler源码分析Handler#构造函数原理Handler#obtainMessage 原理Message源码分析Handler#post的原理Handle

chivalrous 655

京东校招Android主观题全解析:Handler、Binder与性能优化核心考点

在Android技术面试中,考察重点逐渐从API使用转向对底层原理和工程架构的深度理解。Handler消息机制是理解主线程与异步通信的基石,其背后的Looper与MessageQueue设计体现了Android系统的核心调度思想;Binder作为跨进程通信的主力,则展现了系统在性能与安全间的平衡。掌握这些原理不仅有助于回答面试中的追问,更能指导日常开发中的性能优化,例如通过内存泄漏治理和卡顿排查提升应用稳定性。从自定义View的绘制流程到图片加载库的架构设计,再到MVP/MVVM的演进,这些知识点共同构成了

weixin_33894640的博客 347

Android Handler 通信 - 彻底了解 Handler 的通信过程

相关文章链接: 1. Android Handler 通信 - 源码分析与手写 Handler 框架 2. Android Handler 通信 - 彻底了解 Native 层的通信过程 相关源码文件: /frameworks/base/core/java/android/os/Handler.java /frameworks/base/core/java/android/os/MessageQu...

z240336124的专栏 1008
上一篇: 安卓binder驱动内核日志调试打印开放及原理(第一节)
下一篇: 安卓binder驱动内核日志调试打印开放及原理(第二节)
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

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

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

打赏作者

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

抵扣说明:

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

余额充值