Increased accuracy of aapt2 "keep" rules 拥有更高准确性的aapt2的"keep"规则

本文翻译自技术大牛jake wharton的博客,文章链接如下:https://jakewharton.com/increased-accuracy-of-aapt2-keep-rules/ 。本人能力有限,如果哪里翻译的不好,请指出来,共同进步~

aapt2(打包工具(Android Asset Packaging Tool))工具将你的Android应用资源打包成运行时所使用的格式。它也为ProGuard或者R8生成了“keep”规则以便在你资源内部的引用类型不会被移除。仅仅在layout XML引用的View,仅仅在menu XML引用的action providers,还有仅仅在manifest XML里引用的broadcast receiver就是如果不是因为这些规则就会被从最终的APK文件中移除的例子。
早于3.3.0-alpha05的Android Gradle插件,aapt2将会为使用一个参数通配符的类型的构造函数生成“keep”规则。一些针对application类,activity类和view引用的规则如下:

# Referenced at frontend/android/build/intermediates/merged_manifests/release/AndroidManifest.xml:20
-keep class com.jakewharton.sdksearch.SdkSearchApplication { <init>(...); }
# Referenced at frontend/android/build/intermediates/merged_manifests/release/AndroidManifest.xml:28
-keep class com.jakewharton.sdksearch.ui.MainActivity { <init>(...); }
# Referenced at search/ui-android/build/intermediates/packaged_res/release/layout/search.xml:57
-keep class android.support.v7.widget.RecyclerView { <init>(...); }

导出release APK中的这些方法我们得到:

com.jakewharton.sdksearch.SdkSearchApplication <init>()
com.jakewharton.sdksearch.ui.MainActivity <init>()
android.support.v7.widget.RecyclerView <init>(Context)
android.support.v7.widget.RecyclerView <init>(Context, AttributeSet)
android.support.v7.widget.RecyclerView <init>(Context, AttributeSet, int)

SdkSearchApplication和MainActivity仅仅有一个默认的构造函数而RecyclerView拥有三个。就反射查找而言,只有一个构造函数被使用。对于在manifest中的类型默认(无参数)构造函数被使用。对于在layout XML文件中的类型,两个参数的构造函数(Context+AttributeSet)被LayoutInflater调用。通过带有(…)的生成规则,我们强制每个构造函数都被保留,尽管我们只需要其中一个。
从Android Gradle插件version 3.3.0-alpha05开始,新版本aapt2开始被使用,它能够生成更精确的规则,这些规则能够引用反射查找所使用的具体的构造函数。

# Referenced at frontend/android/build/intermediates/merged_manifests/release/AndroidManifest.xml:20
-keep class com.jakewharton.sdksearch.SdkSearchApplication { <init>(); }
# Referenced at frontend/android/build/intermediates/merged_manifests/release/AndroidManifest.xml:28
-keep class com.jakewharton.sdksearch.ui.MainActivity { <init>(); }
# Referenced at search/ui-android/build/intermediates/packaged_res/release/layout/search.xml:57
-keep class android.support.v7.widget.RecyclerView { <init>(android.content.Context, android.util.AttributeSet); }

再次导出release APK中的这些方法我们得到:

com.jakewharton.sdksearch.SdkSearchApplication <init>()
com.jakewharton.sdksearch.ui.MainActivity <init>()
android.support.v7.widget.RecyclerView <init>(Context, AttributeSet)
android.support.v7.widget.RecyclerView <init>(Context, AttributeSet, int)

RecyclerView的(Context)不再出现了!这个构造函数曾经被强制性打包到最终的release APK里尽管他没有被使用到。三个参数的构造函数仍然能够看见是因为两个参数的构造函数调用了它:

public RecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
}

如果优化仍然能够被允许,并且没有其余的地方对这三个参数的构造函数的调用,它有可能变为内联。这些事情不会在老的规则发生。
这看上去像是一个小的变化,也是大部分的变化了。Application,activity和action provider的子类趋向于仅仅有一个构造函数因此它们的计数将不太可能去改变。但是对于View子类,一般都有三或四个构造函数,因此你将看到其中的二或三个被移除。在整个APK的范围里允许十个或者上百个没有必要保持的函数被移除。这个规则的特点不仅仅减少了最终在APK中的方法数量,还通过优化去拥有更好的体验。
如果你对新的规则发现了一些bug,请在[Android issue tracker](https://issuetracker.google.com/issues/new?component=192709)报告他们。

猜你喜欢

转载自blog.csdn.net/y505772146/article/details/83589440
今日推荐