关于anr:项目中多次操作SharedPreferences导致ANR场景的解决

我的项目背景:随着时代的提高,挪动端广告的投放变得越来越多样化,为了靠近市场,不少公司本人研发了SDK去收集用户的一些信息以及行为用于剖析,依据剖析后果应用自定义广告(自定义View)的形式持续向用户进行展现,以进步展现率和点击率。目前对于广告商方面的抉择,国内的广告变现广泛较低,首选应该是接入谷歌广告。随着业务的倒退,在一段时间后,公司开始转变成广告接管方,并靠本人的SDK来进行广告的投放,以及优化。以定位来获取广告的形式为例:· 首先利用用户的定位等权限来获取经纬度 · 将经纬度上传至国内某定位SDK,获取具体信息。· 最初依据定位信息来获取广告并预加载为广告展现做筹备。 所遇到的挑战:在我的项目性能实现后筹备上架前,会对我的项目进行一系列的测试,然而ANR问题在测试过程中很难实现复现,在应用多个机型测试的过程中简直没有ANR问题的记录。然而在用户的理论应用过程中,因为Android碎片化的重大,加上用户的一些操作的习惯等,会导致呈现ANR的问题。面对一些大型的厂家,ANR呈现时会弹窗疏导用户敞开软件,会导致应用体验不好,造成用户的散失。 解决问题的步骤: 在我的项目一个多月的异样收集中,呈现过几次ANR的问题。· 剖析异样收集中ANR日志将问题锁定在SharedPreferences 上,排查过程比拟麻烦,在锁定了问题后,开始对问题进行剖析。· 查看Android文档:在我的项目中,团队应用SharedPreferences读写配置文件,均采纳了官网的举荐做法,调用apply来提交,调用这个办法时,先写入内存中,再将工作退出队列中,会在异步线程中做落盘的操作,这个操作实践上来说是没有问题的,也是google官网举荐的做法。· 浏览源码: 在此过程中发现谷歌官网正文:If another editor on this SharedPreferences does a regular commit() while a apply() is still outstanding, the commit() will block until all async commits are completed as well as the commit itself.翻译:如果SharedPreferences上的另一个编辑器执行惯例的commit(),而apply()依然未实现,则commit()将阻塞,直到所有异步提交以及提交自身都实现。 · 锁定问题:主线程调用了 QueuedWork.waitToFinish(),没有待执行的工作,间接执行 finisher,进行阻塞期待, 直到写入文件胜利后复原执行, 这时候如果等待时间过长, 在一些市面上性能差的中低端机型上就会很容易呈现ANR。 (8.0以下)问题的解决过后的优化: 减小sp对应的文件的大小,依照分类去读写对应的sp文件。sp的读写轻量的、小的配置信息,将相似JSON的数据交给其余形式保留。当须要屡次调用Put系列办法,当逻辑确认不须要立刻读取时,在最初一次调用commit或apply即可。最近敌人推了一篇字节的博客(以下文字以及图片来源于字节今日头条团队)。 · 思路:如果能让sPendingWorkFinishers.poll()返回为null,则这里的期待行为间接就跳过去了,sPendingWorkFinishers是个ConcurrentLinkedQueue汇合,能够间接动静代理这个汇合,覆写poll办法,让其永远返回null,这个时候UI永远不会期待子线程写入文件结束,事实证明这种形式简略无效。 · 针对这种写入期待的ANR问题,还有一种就是全局替换写入形式,通过插桩的形式,替换所有的API实现,采纳其余的存储形式,这种形式修复老本和危险较大,然而前期能够随机的替换存储形式,应用比拟灵便。 友盟平台相干SDK初体验:因为ANR的比拟难复现,于是写一个办法,重复对SharedPreferences进行操作,以达到相似状况的复现。 呈现问题,通过友盟U-APM平台定位: 找到问题后,进行文中思路的操作即可。 总结在情景中,因为Android太过碎片化,又不得间接舍弃低版本用户,采纳接入相似友盟U-APM平台的形式去更快的解决问题是必不可少的。但对于一些小型手机的低版本可能还是会呈现ANR的问题,针对相似收集用户行为的情景,可采取进行多种形式去进行收集,例如对于低版本的零碎,升高对收集数据的完整性等。 作者:计蒙不吃鱼

November 8, 2021 · 1 min · jiezi