点击上方“开发者技术前线”,选择“星标”

每天 14.00 在看 | 真爱

作者: 承香墨影 | 来源:公众号 承香墨影

一. 序

当 App 达到一定体量的时候,肯定是要考虑质量优化。有些小问题,看似只有 0.01% 触发率,但是如果发生在 DAU 过千万的产品中,就不是小问题了。

滴滴这个独角兽的 DAU 早已过千万,自然有一些独到的优化方案。最近滴滴在 Github 上开源了一个 Android App 的质量优化工具 Booster,通过动态发现和加载机制,提供了可扩展的能力。等于是一款移动应用的质量优化框架。

说到优化好像也不知道具体能干什么。从特性上笼统来说,Booster 可以做到性能检测和优化、包体积瘦身、代码注入等。

稍微看了一下,暂时所支持的优化还比较有限,但是好在 Booster 提供了非常便捷的扩展能力,我们可以根据业务场景,进行针对性的优化。

虽然 Booster 现在的优化点还很少,但是在开源的同时,也给出了后续发展的 Roadmap,之后的功能应该是会越来越完善的。下面就来了解一下滴滴新开源的 Booster。

二. Booster

2.1 什么是 Booster

Booster 是专门为移动应用而设计的简单易用、轻量级、功能强大且可扩展的质量优化工具包,其通过动态发现和加载机制,提供了可扩展的能力。是一款移动应用的质量优化框架。

Booster 主要由 Transformer 和 Task 组成。

Transformer 用于对字节码进行扫描或修改(取决于 Transformer 的功能),而 Task 则用于处理构建中的资源。

为了满足不同业务场景下的优化需求,Booster 提供了 Transformer SPI 和 VariantProcessor SPI 接口,来允许开发者进行定制。

Booster 的整体框架如下:

Booster 对 Gradle 还有一些小的版本要求:

2.2 Booster 到底能干什么?

读了一遍官方的介绍,好像还是不知道 Booster 的用处,这里就以 Booster 已经支持的一个 Transformer 为例子,来讲解它到底能干什么。

Toast 是我们在日常开发中经常会用到的一个提示信息的组件,而在 Android 7.0 的系统中,它有可能会触发 BadTokenException 的异常。这个问题,用 Booster 就可以解决。

Toast 抛 BadTokenException 看起来是在显示的时候,窗口的 Token 已经失效了,也有可能在显示 Toast 的时候,窗口已经被销毁了。

android.view.WindowManager$BadTokenException:     at android.view.ViewRootImpl.setView(ViewRootImpl.java)    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java)    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java4)    at android.widget.Toast$TN.handleShow(Toast.java)    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java)    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java4)    at android.widget.Toast$TN.handleShow(Toast.java)

这个问题只出现在 Android 7.0 中,在之后的版本中,Google 的工程师为了解决这个问题,是直接将其 Catch 住这个异常来解决问题的。下面是 Android 8.0 的相关代码。

try {    mWM.addView(mView, mParams);    trySendAccessibilityEvent();} catch (WindowManager.BadTokenException e) {    /* ignore */}    mWM.addView(mView, mParams);    trySendAccessibilityEvent();} catch (WindowManager.BadTokenException e) {    /* ignore */}

这种问题,在我们自己的代码中,可以通过定义一个统一的 Toast 帮助类,将其 方法 catch 住。老项目我们就要全文遍历一遍 Toast 的调用并替换,并且这样的方案也有缺陷,无法避免来自第三方库中使用的 Toast 出现此问题。

虽然这个问题已经有解决方案,但是 Booster 给了我们另外一个选择。

在 Booster 中,已经内置了一些 Transformers,其中就有一个 booster-transform-bugfix-toast,是用于修复 Android 7.0 中,Toast 导致的系统错误。

ToastBugfixTransformer 的主要源码在此:

@AutoService(ClassTransformer::class)class ToastBugfixTransformer : ClassTransformer {    override fun transform(context: TransformContext, klass: ClassNode): ClassNode {        klass.methods.forEach { method ->            method.instructions?.iterator()?.asIterable()?.filterIsInstance(MethodInsnNode::class.java)?.filter {                it.owner == TOAST && it.name == "show" && it.desc == "()V"            }?.forEach {                it.owner = `TOAST'`                it.desc = "(L$TOAST;)V"                it.opcode = Opcodes.INVOKESTATIC            }        }        return klass    }}private const val TOAST = "android/widget/Toast"private const val `TOAST'` = "com/didiglobal/booster/$TOAST"class ToastBugfixTransformer : ClassTransformer {

    override fun transform(context: TransformContext, klass: ClassNode): ClassNode {        klass.methods.forEach { method ->            method.instructions?.iterator()?.asIterable()?.filterIsInstance(MethodInsnNode::class.java)?.filter {                it.owner == TOAST && it.name == "show" && it.desc == "()V"            }?.forEach {                it.owner = `TOAST'`                it.desc = "(L$TOAST;)V"                it.opcode = Opcodes.INVOKESTATIC            }        }        return klass    }}private const val TOAST = "android/widget/Toast"private const val `TOAST'` = "com/didiglobal/booster/$TOAST"

它是将系统的 Toast 传递到另外定制的一个 com.didiglobal.booster.android.widget 包下的 Toast 来解决。

public static void show(final android.widget.Toast toast) {    if (Build.VERSION.SDK_INT == 25) {        workaround(toast).show();    } else {        toast.show();    }}private static android.widget.Toast workaround(final android.widget.Toast toast) {    final Object tn = getFieldValue(toast, "mTN");    if (null == tn) {        Log.w(TAG, "Field mTN of " + toast + " is null");        return toast;    }    final Object handler = getFieldValue(tn, "mHandler");    if (handler instanceof Handler) {        if (setFieldValue(handler, "mCallback", new CaughtCallback((Handler) handler))) {            return toast;        }    }    final Object show = getFieldValue(tn, "mShow");    if (show instanceof Runnable) {        if (setFieldValue(tn, "mShow", new CaughtRunnable((Runnable) show))) {            return toast;        }    }    Log.w(TAG, "Neither field mHandler nor mShow of " + tn + " is accessible");    return toast;}    if (Build.VERSION.SDK_INT == 25) {        workaround(toast).show();    } else {        toast.show();    }}

private static android.widget.Toast workaround(final android.widget.Toast toast) {    final Object tn = getFieldValue(toast, "mTN");    if (null == tn) {        Log.w(TAG, "Field mTN of " + toast + " is null");        return toast;    }

    final Object handler = getFieldValue(tn, "mHandler");    if (handler instanceof Handler) {        if (setFieldValue(handler, "mCallback", new CaughtCallback((Handler) handler))) {            return toast;        }    }

    final Object show = getFieldValue(tn, "mShow");    if (show instanceof Runnable) {        if (setFieldValue(tn, "mShow", new CaughtRunnable((Runnable) show))) {            return toast;        }    }

    Log.w(TAG, "Neither field mHandler nor mShow of " + tn + " is accessible");    return toast;}

当 API Level 不为 25 时,直接调用 Toast.show() 方法,为 25 时,通过反射来判断当前 Toast 的情况,进而返回一个有效的 Toast 对象,再调用 show()

到这里就将 Toast 在 7.0 上的问题修复了,我们正常开发过程中,完全不需要担心 Toast 的使用,质量保证和业务开发就可以安全区分开。

2.3 Booster 已经内置的功能

在 Booster 开源的时候,内部已经内置了一些 Transformer 和 Task,前面介绍的 booster-transform-bugfix-toast 就是其中之一。

内置 Transformers

内置 Tasks

这些 Booster 提供的 Transformer 和 Task,功能还有限,它们更多的是提供一些指导意义,可以让我们通过源码了解到 Booster 是如何使用和工作的。

有更多想法和需要,可以自己去定制实现 Transformer 和 Task。

三. 小结时刻

虽然现在 Booster 的优化功能还有限,但是看其发布的 Roadmap 中,已经提出接下来几个版本的迭代计划,例如会专注:性能优化、Lint、资源压缩、用户体验等等。在性能优化上,会对多线程的使用、SP 的使用、WebView 的预加载进行针对性的优化。

整体来看,Booster 是一个非常好的性能优化框架,它使用的都是成熟的技术,将其包装而成,降低了我们使用的难度。并没有什么太大的深坑,有需要可以进行尝试。

更多内容可以去 Github 上阅读 Wiki 和源码,有兴趣别忘点个 star。

Github:https://github.com/didi/boosterEND

开发者技术前线 ,汇集技术前线快讯和关注行业趋势,大厂干货,是开发者经历和成长的优秀指南。

历史推荐

字节跳动是个疯子!

从简历被刷到拿字节跳动 offer,我花了一年时间

卧槽 ,你居然在代码里下了毒!

不错就点个在看吧!

滴滴 App 质量优化黑科技,都做了什么相关推荐

  1. 滴滴Booster移动APP质量优化框架 学习之旅 二

    推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 续写滴滴Booster移动APP质量优化框架学习之旅,上篇文章分 ...

  2. 滴滴Booster移动APP质量优化框架 学习之旅 三

    推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 滴滴Booster移动App质量优化框架-学习之旅 二对重复资源 ...

  3. 【华为云技术分享】HDC.Cloud | 为防止交通事故,95后学生运用“黑科技”这样做!

    [摘要] 智能车伙伴基于AIoT,利用实时抓取到的图像信息融合实时监测的体征数据,综合判断驾驶员疲劳程度和状态,并发出提醒,最终完成"基于AIoT的驾驶员状态实时监测系统 经常在电视上总会看 ...

  4. 四款全民都在用的app,满满的黑科技

    大方租车 共享租车平台,平时很多的上班族上下班都是做公交和地铁,但过年或者节假日出去玩都离不开车,买一俩车在家里闲置着是核算的,其实可以用此凭条进行租车,只需给部分定金和租金即可. 手机数据恢复精灵 ...

  5. Android 编译速度优化黑科技 - RocketX

    一.背景描述 二.效果展示 三.思路问题分析与模块搭建 四.问题解决与实现 五.一天一个小惊喜 六.下一步展望 一.背景描述 在项目体量越来越大的情况下,编译速度也随着增长,有时候一个修改需要等待长达 ...

  6. 近万米展厅,压箱底的宝贝,雪浪大会最好玩的黑科技都在这了 | 倒计时1天

     关注ITValue,查看企业级市场最新鲜.最具价值的报道! 摘要 雪浪大会是一场"反形式化"的大会,是一场真正聚焦制造业痛点问题的大会.在这里,不但有两天烧脑的营养补给--大会主 ...

  7. 腾讯成本优化黑科技:整机CPU利用率最高提升至90%

    腾讯TLinux团队提出了一套全新的混部方案,在不影响在线业务的前提下,对整机CPU利用率提升效果非常明显,在有的业务场景下,整机CPU利用率甚至能提升至90%. 一.前言   腾讯运营着海量的服务器 ...

  8. “本地资源检测” 上手指南,玩转最前沿的优化黑科技!

    UWA本地资源检测是对游戏.VR等项目工程的资源.代码和设置等进行自动检测的服务,是项目研发持续集成.持续交付流程中的重要一环,旨在为游戏研发制定资源与代码规范,帮助研发团队快速发现和解决项目中的性能 ...

  9. 有了这7个高质量的黑科技软件,工作效率翻倍!

    推荐7个必备的神器软件. 1.uTools uTools是一款免费桌面启动器,它是一个可随时呼出的的输入框 (搜索框),但和Listary等快捷启动器工具不太一样的是,除了可以快速启动应用之外,它更加 ...

最新文章

  1. ios小项目——新浪微博客户端总结
  2. 初探运算符重载------(减号)
  3. React 实现 百度搜索框(简易)
  4. linux检查系统硬件信息命令,Linux查看系统信息(硬件信息, 系统设置信息等) 命令 | Soo Smart!...
  5. 噪声调频 matlab,如何用matlab编写噪声调频干扰信号
  6. 动态规划 1.背包问题
  7. java中的泛型是什么_Java中泛型是什么?Java泛型的详细介绍
  8. poj 3126 BFS
  9. [yum] yum加速
  10. shell 后台运行程序并写pid文件
  11. ElasticSearch全文搜索引擎之Windows集群搭建
  12. Word打开后出现乱码
  13. html 字怎么居中怎么写,html文字居中代码怎么写
  14. lzg_ad:Windows Embedded Standard 安装说明
  15. Lighttpd介绍
  16. Node.js 网页瘸腿稍强点爬虫再体验
  17. 关于山东大学(青岛)的吐槽
  18. 《软件测试》第二章 软件开发的过程
  19. 正负数值的正则表达式
  20. 几个简单好用的APP分享给你

热门文章

  1. GimbalLock万向节锁与四元数旋转
  2. 计算机科学的知识单元,[计算机科学与技术专业的知识体系与课程体系..ppt
  3. 一个让echarts中国地图包含省市轮廓的技巧
  4. pango design suite使用外部编辑器
  5. COCOS2DX 与 UNITY3D 的发展浅谈
  6. C#写的网上订舱辅助系统,OTM订舱辅助
  7. JS使用RSA非对称加密方式加密传输数据
  8. 浅谈雅诗兰黛微博营销方式
  9. 生产成本核算岗工作流程
  10. 全球及中国商业无线雷管行业研究及十四五规划分析报告