一. 序

当 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,开源了!的更多相关文章

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

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

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

    推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 一.Booster简介 Booster是滴滴最近开源一个的移动应 ...

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

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

  4. 基于.NET平台常用的框架和开源程序整理

    自从学习.NET以来,优雅的编程风格,极度简单的可扩展性,足够强大开发工具,极小的学习曲线,让我对这个平台产生了浓厚的兴趣,在工作和学习中 也积累了一些开源的组件,就目前想到的先整理于此,如果再想到, ...

  5. 10 个打造 React.js App 的最佳 UI 框架

    10 个打造 React.js App 的最佳 UI 框架 在本文中,我们将分享一些助你打造 React.js App 最佳的 UI 框架.它们具备你所需要的基本 React 组件,以及易用的 API ...

  6. App Store评论优化,让你的APP评论上涨

    App Store评论优化怎么做 App Store评论优化,让你的APP评论上涨 关于「ASO评论优化」,主要分为三块.换评论,买评论,引导用户写评论. 可能有些刚接触ASO的朋友会问,为什么要给A ...

  7. CLion之C++框架篇-优化框架,引入boost(三)

      背景   结合上一篇CLion之C++框架篇-优化框架,单元测试(二),继续进行框架优化!这一版优化引入一个我们日常经常使用的操作库Boost,估算使用频率在70%以上!   Boost的优势在哪 ...

  8. CLion之C++框架篇-优化框架,单元测试(二)

    背景   结合上一篇CLion之C++框架篇-安装工具,基础框架的搭建(一),继续进行框架优化!   googletest(GTest)是Google开源的C++测试框架,与CLion组合,对C++环 ...

  9. MUI简介-最接近原生App体验的前端框架

    MUI简介-最接近原生App体验的前端框架 一.总结 一句话总结:最接近原生App体验的前端框架 二.多端发布 – 开发一套代码,发布六个平台 真正彻底的跨平台开发,不是简单的跨iOS和Android ...

随机推荐

  1. tar结果find打包指定后缀的文件

    find 目录名 -name "*.ini" | xargs tar czvf tarch.tar.gz  tar czf tmp.tar.gz tmp/ --exclude=&q ...

  2. C++:LIB和DLL的区别与使用

    共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library. 一种是LIB包含 ...

  3. 关于Resin SSL支持的两个问题

    1.Resin的OpenSLL支持功能只有收费Pro版才支持,这一点,只有你做好配置,测试的时候才会在提示中发现,文档里没有说明. 2.它的官方文档这部分有问题,第一个问题就是上面第一条没有说,第二个 ...

  4. 从Freelancer的热门Skill看看你应该学什么?

    以下数据是2012-1-31号数据. Websites, IT & Software: PHP (2402)HTML (1639)SEO(877)MySQL (836)Link Buildin ...

  5. iOS9自动布局神器StackView

    http://www.jianshu.com/p/767f72b7d754 这篇文章紧跟上边autolayout的一些小技巧,如果你没有看过,不防先看下<你真的会用autolayout吗?> ...

  6. java解析xml字符串方法

    一,用DOM4J  针对无重复标签的xml字符串格式,如下: 针对此种情况可用DOM4J解析法,引入 dom4j的相关jar包代码如下: Document document=DocumentHelpe ...

  7. 实现MyArrayList类深入理解ArrayList

    ArrayList简介 ArrayList是一个动态数组,Array的复杂版本,它提供了动态的增加和减少元素,实现了ICollection和IList接口,灵活的设置数组的大小等好处. MyArray ...

  8. 智能指针auto_ptr & shared_ptr

    转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...

  9. 高质量的内容是SEO的关键

    内容是最有效的SEO策略,但也是最难执行的 正确的目录对SEO(搜索引擎优化:search engine optimization)关乎重大.根据Ascend2在2014年4月对全球营销专业人士做的调 ...

  10. redis主从相关问题

    redis主从是如何实现同步的 第一次.Slave向Master同步的实现是:        Slave向Master发出同步请求(发送sync命令),Master先dump出rdb文件,然后将rdb ...