源文件
class  MainActivity  : AppCompatActivity  () {    override  fun  onCreate (savedInstanceState: Bundle ?)   {         super .onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         Log.i("yeshu" , "hello log" )     } } 
 
反编译后到smali文件
.method  protected  onCreate(Landroid/os/Bundle; )V    .locals  1    .line  10    invoke-super  {p0, p1}, Landroidx/appcompat/app/AppCompatActivity; ->onCreate(Landroid/os/Bundle; )V     const  p1, 0x7f0a001c     .line  11    invoke-virtual  {p0, p1}, Lcom/example/logdemo/MainActivity; ->setContentView(I)V     const-string  p1, "yeshu"      const-string  v0, "hello log"      .line  12    invoke-static  {p1, v0}, Landroid/util/Log; ->i(Ljava/lang/String; Ljava/lang/String; )I     return-void  .end method 
 
koin转换得到的java文件
@Metadata(bv = {1, 0, 3}, d1 = {"\000\030\n\002\030\002\n\002\030\002\n\002\b\002\n\002\020\002\n\000\n\002\030\002\n\000\030\0002\0020\001B\005\006\002\020\002J\022\020\003\032\0020\0042\b\020\005\032\004\030\0010\006H\024\006\007"}, d2 = {"Lcom/example/logdemo/MainActivity;", "Landroidx/appcompat/app/AppCompatActivity;", "()V", "onCreate", "", "savedInstanceState", "Landroid/os/Bundle;", "app_release"}, k = 1, mv = {1, 1, 16}) public  final  class  MainActivity  extends  AppCompatActivity   {  private  HashMap _$_findViewCache;      public  void  _$_clearFindViewByIdCache() {     HashMap hashMap = this ._$_findViewCache;     if  (hashMap != null )       hashMap.clear();    }      public  View _$_findCachedViewById(int  paramInt) {     if  (this ._$_findViewCache == null )       this ._$_findViewCache = new  HashMap<Object, Object>();      View view2 = (View)this ._$_findViewCache.get(Integer.valueOf(paramInt));     View view1 = view2;     if  (view2 == null ) {       view1 = findViewById(paramInt);       this ._$_findViewCache.put(Integer.valueOf(paramInt), view1);     }      return  view1;   }      protected  void  onCreate (Bundle paramBundle)   {     super .onCreate(paramBundle);     setContentView(2131361820 );     Log.i("yeshu" , "hello log" );   } } 
 
没有开启混淆优化时 class  MainActivity  : AppCompatActivity  () {    val  debug: Boolean  = false      override  fun  onCreate (savedInstanceState: Bundle ?)   {         super .onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         if  (debug){             Log.i("yeshu" , "hello log" )         } else  {             Log.i("yeshu" , "hello log  true" )         }     }     private  fun  test ()   {         Log.i("yeshu" , "wo shen me dou mei zuo " )     } } 
 
val debug 会让编译器优化掉无效的语句,但是var debug不会。 
默认的无效方法 test()没有被删除掉 
 
开启混淆,优化 启用压缩,优化,混淆后只要逻辑上没执行到的代码就被删除了,依赖库中没用到的代码也都删除了。
 
public  final  class  MainActivity  extends  h   {  public  void  onCreate (Bundle paramBundle)   {     super .onCreate(paramBundle);     setContentView(2131361820 );     Log.i("yeshu" , "hello log  true" );   } } 
 
class  MainActivity  : AppCompatActivity  () {    var  debug: Boolean  = false      override  fun  onCreate (savedInstanceState: Bundle ?)   {         super .onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         if  (debug){             Log.i("yeshu" , "hello log" )             test()         } else  {             Log.i("yeshu" , "hello log  true" )         }     }     private  fun  test ()   {         Log.i("yeshu" , "wo shen me dou mei zuo " )     } } 
 
test()方法和if判断中的false分支都会被删除
子module和主项目之间的混淆配置关系 AAR 库:<library-dir>/proguard.txt
JAR 库:<library-dir>/META-INF/proguard/
如果某个 AAR 库是使用它自己的 ProGuard 规则文件发布的,并且您将该 AAR 库作为编译时依赖项纳入到项目中,则 R8 在编译项目时会自动应用其规则。
如果 AAR 库需要某些保留规则才能正常运行,那么使用该库随附的规则文件将非常有用。 也就是说,库开发者已经为您执行了问题排查步骤。
不过,请注意,由于 ProGuard 规则是累加的,因此 AAR 库依赖项包含的某些规则无法移除,并且可能会影响对应用其他部分的编译。例如,如果某个库包含停用代码优化的规则,该规则会针对整个项目停用优化
查看整个项目的规则 要输出 R8 在构建项目时应用的所有规则的完整报告,请将以下代码添加到模块的 proguard-rules.pro 文件中:
// You can specify any path and filename.     -printconfiguration ~/tmp/full-r8-config.txt 
 
给不同的flavor配置不同的混淆规则 android {         ...         buildTypes {             release {                 minifyEnabled true                 proguardFiles getDefaultProguardFile(                   'proguard-android-optimize.txt'),                   // List additional ProGuard rules for the given build type here. By default,                   // Android Studio creates and includes an empty rules file for you (located                   // at the root directory of each module).                   'proguard-rules.pro'             }         }         flavorDimensions "version"         productFlavors {             flavor1 {               ...             }             flavor2 {                 proguardFile 'flavor2-rules.pro'             }         }     }      
 
自定义要保留的代码 说明了它在什么情况下可能会错误地移除代码:
当您的应用通过 Java 原生接口 (JNI) 调用方法时 
当您的应用在运行时查询代码时(如使用反射) 
 
-keep public class MyClass @Keep 
 
缩减资源 两个必须同时开启
shrinkResources true minifyEnabled true 
 
移除未使用的备用资源 以下代码段展示了如何设置只保留英语和法语的语言资源:
android {         defaultConfig {             ...             resConfigs "en", "fr"         }     }      
 
重复资源的合并规则 Gradle 会按以下级联优先顺序合并重复资源:
依赖项 → 主资源 → 版本变种 → 版本类型
例如,如果某个重复资源同时出现在主资源和版本变种中,Gradle 会选择版本变种中的资源。
R8代码优化 
如果您的代码从未采用过给定 if/else 语句的 else {} 分支,R8 可能会移除 else {} 分支的代码。 
如果您的代码只在一个位置调用某个方法,R8 可能会移除该方法并将其内嵌在这一个调用点。 
如果 R8 确定某个类只有一个唯一的子类且该类本身未实例化(例如,一个仅由一个具体实现类使用的抽象基类),它就可以将这两个类合并在一起并从应用中移除一个类。 
 
生成移除的(或保留的)代码的报告 是否可以根据移除报告来优化代码,提高代码质量
排查资源缩减问题 同样通过查看资源压缩日志,来提高代码质量
删除log日志 -assumenosideeffects class android.util.Log {           public static boolean isLoggable(java.lang.String, int);           public static int v(...);           public static int i(...);           public static int w(...);           public static int d(...);           public static int e(...);       } 
 
不管代码有没有执行,都会直接删除掉
class  MainActivity  : AppCompatActivity  () {    var  debug: Boolean  = false      override  fun  onCreate (savedInstanceState: Bundle ?)   {         super .onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         if  (debug){             Log.i("yeshu" , "hello log" )             test()         } else  {             Log.i("yeshu" , "hello log  true" )         }     }     private  fun  test ()   {         Log.i("yeshu" , "wo shen me dou mei zuo " )     } }	 
 
public  final  class  MainActivity  extends  h   {  public  void  onCreate (Bundle paramBundle)   {     super .onCreate(paramBundle);     setContentView(2131361820 );   } } 
 
反编译出来的java文件和源文件的区别 # virtual methods .method public onCreate(Landroid/os/Bundle;)V     .locals 1     invoke-super {p0, p1}, La/b/k/h;->onCreate(Landroid/os/Bundle;)V     const p1, 0x7f0a001c     invoke-virtual {p0, p1}, La/b/k/h;->setContentView(I)V     const-string p1, "hello log"     const-string v0, "yeshu"     .line 1     invoke-static {v0, p1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I     return-void .end method 
 
public  final  class  MainActivity  extends  h   {  public  void  onCreate (Bundle paramBundle)   {     super .onCreate(paramBundle);     setContentView(2131361820 );     Log.v("yeshu" , "hello log" );   } } 
 
源文件
class  MainActivity  : AppCompatActivity  () {    override  fun  onCreate (savedInstanceState: Bundle ?)   {         super .onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         MyLog.log("hello log" )     } } 
 
object  MyLog {    var  debug: Boolean  = true      fun  log (msg: String )   {         if  (debug) {             Log.v("yeshu" , msg)         }     } } 
 
参考 https://developer.android.com/studio/build/shrink-code#shrink-code