滴滴 App 的质量优化框架 Booster,开源了!


一. 序
当 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 还有一些小的版本要求:
- Gradle 4.1 以上版本
- Android Gradle 插件 3.0 以上版本
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)
这个问题只出现在 Android 7.0 中,在之后的版本中,为了解决这个问题,是直接将其 Catch 住这个异常来解决问题的。下面是 Android 8.0 的相关代码。
try {
mWM.addView(mView, mParams);
trySendAccessibilityEvent();
} catch (WindowManager.BadTokenException e) {
/* ignore */
}
虽然这个问题已经有了一些解决方案,但是 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"
它是将系统的 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;
}
当 API Level 不为 25 时,直接调用 Toast.show() 方法,为 25 时,通过反射来判断当前 Toast 的情况,进而返回一个有效的 Toast 对象,再调用 show() 。
到这里就将 Toast 在 7.0 上的问题修复了,我们正常开发过程中,完全不需要担心 Toast 的使用,做质量保证的和做业务的也可以区分开了。
2.3 Booster 已经内置的功能
在 Booster 开源的时候,内部已经内置了一些 Transformer 和 Task,前面介绍的 booster-transform-bugfix-toast 就是其中之一。
内置 Transformers
- booster-transform-bugfix-toast:修复 7.0 中 Toast 导致的系统错误。
- booster-transform-lint:检查潜在的性能问题。
- booster-transform-shrink:用于清除 class 文件中的常量。
- booster-transform-usage:用于扫描特定 API 的使用情况。
内置 Tasks
- Booster-task-artifact:提供显示 artifact 的 Task。
- Booster-task-dependency:提供显示所有依赖项的标识符以及文件路径的 Task。
- Booster-task-permission:提供显示所有依赖项使用的 Android 权限。
这些 Booster 提供的 Transformer 和 Task,功能还有限,它们更多的是提供一些指导意义,可以让我们通过源码了解到 Booster 的使用。
有更多想法,可以自己去实现 Transformer 和 Task。
在发布的 Roadmap 中,已经提出接下来几个版本的迭代计划,例如会专注:性能优化、Lint、资源压缩、用户体验等等。在性能优化上,会对多线程的使用、SP 的使用、WebView 的预加载进行针对性的优化。
三. 小结时刻
整体来看,Booster 是一个非常好的性能优化框架,它使用的都是成熟的技术,将其包装而成,降低了我们使用的难度。并没有什么太大的深坑,有需要可以进行尝试。
更多内容可以去 Github 上阅读 Wiki 和源码,有兴趣别忘点个 star。
Github:https://github.com/didi/booster
本文对你有帮助吗?留言、点赞、转发是最大的支持,谢谢!
公众号后台回复成长『成长』,将会得到我准备的学习资料,也能回复『加群』,一起学习进步;你还能回复『提问』,向我发起提问。

滴滴 App 的质量优化框架 Booster,开源了!的更多相关文章
- 滴滴Booster移动APP质量优化框架 学习之旅 二
推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 续写滴滴Booster移动APP质量优化框架学习之旅,上篇文章分 ...
- 滴滴Booster移动APP质量优化框架 学习之旅
推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 一.Booster简介 Booster是滴滴最近开源一个的移动应 ...
- 滴滴Booster移动APP质量优化框架 学习之旅 三
推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 滴滴Booster移动App质量优化框架-学习之旅 二对重复资源 ...
- 基于.NET平台常用的框架和开源程序整理
自从学习.NET以来,优雅的编程风格,极度简单的可扩展性,足够强大开发工具,极小的学习曲线,让我对这个平台产生了浓厚的兴趣,在工作和学习中 也积累了一些开源的组件,就目前想到的先整理于此,如果再想到, ...
- 10 个打造 React.js App 的最佳 UI 框架
10 个打造 React.js App 的最佳 UI 框架 在本文中,我们将分享一些助你打造 React.js App 最佳的 UI 框架.它们具备你所需要的基本 React 组件,以及易用的 API ...
- App Store评论优化,让你的APP评论上涨
App Store评论优化怎么做 App Store评论优化,让你的APP评论上涨 关于「ASO评论优化」,主要分为三块.换评论,买评论,引导用户写评论. 可能有些刚接触ASO的朋友会问,为什么要给A ...
- CLion之C++框架篇-优化框架,引入boost(三)
背景 结合上一篇CLion之C++框架篇-优化框架,单元测试(二),继续进行框架优化!这一版优化引入一个我们日常经常使用的操作库Boost,估算使用频率在70%以上! Boost的优势在哪 ...
- CLion之C++框架篇-优化框架,单元测试(二)
背景 结合上一篇CLion之C++框架篇-安装工具,基础框架的搭建(一),继续进行框架优化! googletest(GTest)是Google开源的C++测试框架,与CLion组合,对C++环 ...
- MUI简介-最接近原生App体验的前端框架
MUI简介-最接近原生App体验的前端框架 一.总结 一句话总结:最接近原生App体验的前端框架 二.多端发布 – 开发一套代码,发布六个平台 真正彻底的跨平台开发,不是简单的跨iOS和Android ...
随机推荐
- C++string函数之strcpy_s
strcpy_s和strcpy()函数的功能几乎是一样的.strcpy函数,就象gets函数一样,它没有方法来保证有效的缓冲区尺寸,所以它只能假定缓冲足够大来容纳要拷贝的字符串.在程序运行时,这将导致 ...
- OO,OO以后,及其极限
1.什么是软件开发? 软件开发的过程就是人们使用各种计算机语言将人们关心的现实世界映射到计算机世界的过程: 现在的计算机的数学理论基础是由计算机的开山鼻祖,大名鼎鼎的图灵于1937年提出的图灵机模型. ...
- No module named zope.interface error的解决
明明安装了 zope.interface,还是出现标题错误,错误语句是 from zope.interface import ooxx 根据 http://stackoverflow.com/ques ...
- 爬取廖雪峰的python3教程
从廖雪峰老师的python教程入门的,最近在看python爬虫,入手了一下 代码比较low,没有用到多线程和ip代理池 然后呢,由于robots.txt的限定,构建了一些user-agent,并放慢的 ...
- Ocelot中文文档-认证
为了验证ReRoutes并随后使用Ocelot的任何基于声明的功能,如授权或使用令牌中的值修改请求. 用户必须像往常一样在他们的Startup.cs中注册认证服务,但他们给每个注册提供了一个方案(认证 ...
- XGBoost算法--学习笔记
学习背景 最近想要学习和实现一下XGBoost算法,原因是最近对项目有些想法,准备做个回归预测.作为当下比较火的回归预测算法,准备直接套用试试效果. 一.基础知识 (1)泰勒公式 泰勒公式是一个用函数 ...
- css 实现文字自动换行切同行元素高度自适应
1.实现div行内布局所有行跟随最大高度自适应 html代码样例: <div class="row-single"> <div class="colsp ...
- [CVPR2015] Is object localization for free? – Weakly-supervised learning with convolutional neural networks论文笔记
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "Helvetica Neue"; color: #323333 } p. ...
- ThreadPoolExcuter源码解析(一)
1.ThreadPoolExcuter原理说明 首先我们要知道为什么要使用ThreadPoolExcuter,具体可以看看文档中的说明: 线程池可以解决两个不同问题:由于减少了每个任务的调用开销,在执 ...
- Spring @Conditional注解的使用
Spring Boot的强大之处在于使用了Spring 4框架的新特性:@Conditional注释,此注释使得只有在特定条件满足时才启用一些配置. 下面来介绍如何使用Condition 首先写一个类 ...