Booster是一款专门为移动应用设计的易用、轻量级且可扩展的质量优化框架,其目标主要是为了解决随着 APP 复杂度的提升而带来的性能、稳定性、包体积等一系列质量问题。它提供了性能检测、多线程优化、资源索引内联、资源去冗余、资源压缩、系统 Bug 修复等一系列功能模块,可以使得稳定性能够提升 15% ~ 25%,包体积可以减小 1MB ~ 10MB。
buildscript {
ext.booster_version = '4.16.2'
repositories {
google()
mavenCentral()
// OPTIONAL If you want to use SNAPSHOT version, sonatype repository is required.
maven { url 'https://oss.sonatype.org/content/repositories/public' }
}
dependencies {
classpath "com.didiglobal.booster:booster-gradle-plugin:$booster_version" // ①
// ② figure out the features you really need, then choose the right module for integration
// ② 弄清楚真正需要的特性,然后从下面的模块列表中选择正确的模块进行集成
}
}
allprojects {
repositories {
google()
mavenCentral()
// OPTIONAL If you want to use SNAPSHOT version, sonatype repository is required.
maven { url 'https://oss.sonatype.org/content/repositories/public' }
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.didiglobal.booster' // ③
- booster-test-asm – Support running unit test with ASM based transformerclasspath “com.didiglobal.booster:booster-task-asm:$booster_version”
- booster-test-javassist – Support running unit test with Javassist based transformerclasspath “com.didiglobal.booster:booster-task-javassist:$booster_version”
本文就主要来分析一下上面两个问题: booster
的核心实现原理和booster
的框架设计。
Gradle 插件
在gradle
中, 插件是用来模块化和重用的组件。我们可以在插件中定义一些常用的方法,以及一些自定义Task。然后把这个插件提供给其他人使用。
booster
也是一个gradle
插件:
//app.gradle
apply plugin: 'com.didiglobal.booster'
编写一个插件需要使用gradle api
, 并继承自Plugin<Project>
build.gradle
dependencies {
compile gradleApi()
}
BoosterPlugin.kt
class BoosterPlugin : Plugin<Project> {
override fun apply(project: Project) {
...
}
}
booster
插件是在gradle 工程配置阶段
时加载的。对于gradle
插件的编写和gradle
的构建生命周期可以参考这两篇文章:
SPI 与 ServiceLoader
SPI
全称Service Provider Interface, 它提供了一种机制:为某个接口寻找实现实例的机制, 而ServiceLoader
是用来实现SPI
的核心类。
理解
SPI
可以参考这篇文章 : https://juejin.im/post/5b9b1c115188255c5e66d18c
booster transform 实现
整个booster
框架中有许多transform
: booster-transform-activity-thread
、booster-transform-thread
等等。
booster
利用SPI
对Transform
的编写做了高度的抽象,从而使在booster
中编写一个transform
十分的容易:
class BoosterPlugin : Plugin<Project> {
override fun apply(project: Project) {
when {
project.plugins.hasPlugin("com.android.application") -> project.getAndroid<AppExtension>().let { android ->
android.registerTransform(BoosterAppTransform()) // 加载所有的 transform
...
}
...
}
}
}
即在注册插件时注册了BoosterAppTransform
,BoosterAppTransform
继承自BoosterTransform
:
abstract class BoosterTransform : Transform() {
override fun getName() = "booster"
override fun isIncremental() = true
override fun getInputTypes(): MutableSet<QualifiedContent.ContentType> = TransformManager.CONTENT_CLASS
final override fun transform(invocation: TransformInvocation?) {
invocation?.let {
BoosterTransformInvocation(it).apply {
if (isIncremental) {
onPreTransform(this)
doIncrementalTransform()
} else {
buildDir.file(AndroidProject.FD_INTERMEDIATES, "transforms", "dexBuilder").let { dexBuilder ->
if (dexBuilder.exists()) {
dexBuilder.deleteRecursively()
}
}
outputProvider.deleteAll()
onPreTransform(this)
doFullTransform()
}
this.onPostTransform(this)
}
}
}
}
即BoosterTransform
的实际工作交给了BoosterTransformInvocation
。他是TransformInvocation
的代理类,这个类会使用ServiceLoader
加载所有的transform
, 并依次调用transform
方法:
internal class BoosterTransformInvocation(private val delegate: TransformInvocation) : TransformInvocation{
private val transformers = ServiceLoader.load(Transformer::class.java, javaClass.classLoader).toList()
internal fun doFullTransform() {
this.inputs.parallelStream().forEach { input ->
input.directoryInputs.parallelStream().forEach {
project.logger.info("Transforming ${it.file}")
it.file.transform(outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.DIRECTORY)) { bytecode ->
bytecode.transform(this)
}
}
input.jarInputs.parallelStream().forEach {
project.logger.info("Transforming ${it.file}")
it.file.transform(outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.JAR)) { bytecode ->
bytecode.transform(this)
}
}
}
}
}
- booster-aapt2 – AAPT2 相关 APIimplementation “com.didiglobal.booster:booster-aapt2:$booster_version”
- booster-api – Booster 插件开发 APIthis module contains both booster-transform-spi and booster-task-spiimplementation “com.didiglobal.booster:booster-api:$booster_version”
- booster-cha – Class Hierarchy Analysis APIimplementation “com.didiglobal.booster:booster-cha:$booster_version”
- booster-command – SPI for external command discoveryimplementation “com.didiglobal.booster:booster-command:$booster_version”
Performance
- booster-task-analyser – 静态分析工具classpath “com.didiglobal.booster:booster-task-analyser:$booster_version”
- booster-transform-thread – 多线程优化classpath “com.didiglobal.booster:booster-transform-thread:$booster_version”
- booster-transform-webview – WebView 预加载classpath “com.didiglobal.booster:booster-transform-webview:$booster_version”
- booster-transform-shared-preferences –
SharedPreferences
优化classpath “com.didiglobal.booster:booster-transform-shared-preferences:$booster_version”
Package Size
- booster-task-compression-cwebp – 采用 cwebp 对资源进行压缩classpath “com.didiglobal.booster:booster-task-compression-cwebp:$booster_version”The option
android.precompileDependenciesResources
need to be set on Android Gradle Plugin 3.6 and higherandroid.precompileDependenciesResources=false - booster-task-compression-pngquant – 采用 pngquant 对资源进行压缩classpath “com.didiglobal.booster:booster-task-compression-pngquant:$booster_version”The option
android.precompileDependenciesResources
need to be set on Android Gradle Plugin 3.6 and higherandroid.precompileDependenciesResources=falsebooster-pngquant-provider could be used for image compressing by pngquant without installation - booster-task-compression-processed-res – ap_ 文件压缩classpath “com.didiglobal.booster:booster-task-compression-processed-res:$booster_version”
- booster-task-resource-deredundancy – 去冗余资源classpath “com.didiglobal.booster:booster-task-resource-deredundancy:$booster_version”The option
android.precompileDependenciesResources
need to be set on Android Gradle Plugin 3.6 and higherandroid.precompileDependenciesResources=false - booster-transform-r-inline – 资源索引内联classpath “com.didiglobal.booster:booster-transform-r-inline:$booster_version”
- booster-transform-br-inline – DataBinding BR索引内联classpath “com.didiglobal.booster:booster-transform-br-inline:$booster_version”
System Bug
- booster-transform-finalizer-watchdog-daemon – 修复 finalizer 导致的
TimeoutException
classpath “com.didiglobal.booster:booster-transform-finalizer-watchdog-daemon:$booster_version” - booster-transform-media-player – 修复 MediaPlayer 崩溃classpath “com.didiglobal.booster:booster-transform-media-player:$booster_version”
- booster-transform-res-check – 检查覆盖安装导致的 Resources 和 Assets 未加载的 Bugclasspath “com.didiglobal.booster:booster-transform-res-check:$booster_version”
- booster-transform-toast – 修复 Toast 在 Android 7.1 上的 Bugclasspath “com.didiglobal.booster:booster-transform-toast:$booster_version”
- booster-transform-activity-thread – 处理系统 Crashclasspath “com.didiglobal.booster:booster-transform-activity-thread:$booster_version”
Utility
- booster-task-check-snapshot – 检查 SNAPSHOT 版本classpath “com.didiglobal.booster:booster-task-check-snapshot:$booster_version”
- booster-task-list-permission – 显示 AAR 使用的权限清单classpath “com.didiglobal.booster:booster-task-list-permission:$booster_version”
- booster-task-list-shared-library – 显示 AAR 包含的动态库清单classpath “com.didiglobal.booster:booster-task-list-shared-library:$booster_version”
Unit Test
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20176,转载请注明出处。
评论0