一. 序

当 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. maven jsp out.print()request.getParameter() 爆红

    如图: 解决方案: 在pom文件中添加依赖: <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->&l ...

  2. 对cordova插件配置文件plugin.xml的理解

    1.配置文件表头包括了插件id,是用于唯一标识插件的.同时插件配置了一个插件名称. 2.这个文件从工作机制,也就是js代码一直到native的java插件代码工作分成两个流程.第一个流程是从代码到插件 ...

  3. JavaScript高级程序设计(一)

    一.三种常见的著名的命名规则: 1.Camel(驼峰式命名):首字母是小写的,接下来的单词都以大写字母开头.例如:var  myTestValue=0; 2.Pascal(帕斯卡命名):首字母是大写的 ...

  4. 30岁天才上班族利用Python人脸监控BOSS,伪装成认真上班的样子!

    如今Python程序员可以做深度学习算法实现人脸识别,得益于国外开源框架,虽然它不能达到face++和众多人脸识别公司,但实际应用并没有受到太大的压力.下图为tensorflow的5点定位加情感测试. ...

  5. webpack4.x版本splitChunksPlugin的配置项详解与实际应用场景

    在工程化地使用webpack时,公共代码抽离是不可或缺的,4.x版本之后,commonsChunkPlugin已经被去掉,splitChunksPlugins登上舞台,并且优化了很多配置选项,集体课件 ...

  6. CSS学习笔记六:写原生导航栏

    因为刚开始学习CSS时,只了解了一些基本样式,然后就跑去学习bootstrap.bootstrap是个不错的东西,挺好玩,起码让你写界面写的轻轻松松,几行引入代码,再来个复制粘贴就解决了,而且boot ...

  7. PAT1107:Social Clusters

    1107. Social Clusters (30) 时间限制 1000 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue When ...

  8. Linux文本处理命令 -- awk

    简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...

  9. Redis配置文件中关于bind参数

    在配置文件redis.conf中,默认的bind 接口是127.0.0.1,也就是本地回环地址.这样的话,访问redis服务只能通过本机的客户端连接,而无法通过远程连接,这样可以避免将redis服务暴 ...

  10. awk 手册

    1. 前言 有关本手册 : 这是一本awk学习指引, 其重点着重于 : l        awk 适于解决哪些问题 ? l        awk 常见的解题模式为何 ? 为使读者快速掌握awk解题的模 ...