性能优化:如何彻底解决SharedPreferences造成的卡顿

背景

在上线 ANR 监控平台后,线上收集到了较多的ANR日志 ,从火焰图信息上看,函数阻塞在了QueuedWork 相关函数上 ,本文主要介绍的这一现象的原因以及如何解决这一问题。

本文介绍的解决方案,已放到github 上https://github.com/Knight-ZXW/SpWaitKiller , 供参考实现

SP任务 阻塞主线程导致ANR的原理

首先简单介绍下 QueuedWork这个类,QueuedWork主要是用来执行和跟踪一些进程全局的工作,但目前主要调度的SP相关的异步任务 ,当调用 SharedPreferences的 applay方法时,其所要执行的SP文件变更操作会被转化成对应的任务 并调用QueuedWork.queue 方法发送到QueuedWork类中进行执行。

同时,系统为了保证这些任务在一些关键动作触发前(如 页面跳转启动Activity) 已经被执行完成, 设计了一个等待机制。简单描述一下这个机制

•SP的apply操作 会产生2个Runnable对象,其实一个为具体文件修改的工作任务(Work Runnable),另一个为 等待任务(awitCommit), 当工作任务被执行完成时,会通过一个CountDownLatch[1]对象通知 等待任务,而awitCommit内部主要就是等待这个CountDownLatch计数器
•工作任务最终会通过 QueueWork的queue被发送到异步线程执行
•等待任务(awitCommit)会通过QueueWork的addFinisher函数被添加到 QueueWork内部的等待队列中
•最后,在系统的一些关键流程,比如ActivityThread执行handleStopActivity时会通过waitToFinish保证这些异步任务都已经被执行完成

而此时如果系统资源(cpu、io)比较紧张、或者是提交的异步任务较多,则可能导致onStop执行时间较长,从而导致ANR。

另外 在Android 8.0.0 以上的版本,google 在 waitToFinish的实现中做了一些改动,在原有的等待所有异步任务执行完成的基础上,会通过调用 processPendingWork

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值