Kotlin - D8,R8和enum

文章目录[x]
  1. 0.1:D8和R8
  2. 0.2:enum和when表达式

D8和R8

有3种编译器可以用来编译运行Android开发写的Kotlin代码。

  • Kotlin编译器:可以运行并转换Kotlin代码为Java字节码。
  • D8:它将Java字节码转换为Dex代码,这时就可以运行应用了。
  • R8:用于优化和缩小应用(主要是ProGuard的替代品)

R8在默认情况下未开启,如果想使用R8则需要在build.gradleminifyEnabled设置为true

buildTypes {
  release {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  }
 }

这迫使R8可以优化并缩小应用。

enum和when表达式

enum class BlendMode{
    OPAQUE,
    FADE,
    ADD,
    TRANSPARENT
}


fun blend(blend:BlendMode){
    when(blend){
        BlendMode.OPAQUE->op()
        BlendMode.FADE->fade()
        BlendMode.ADD->add()
        BlendMode.TRANSPARENT->trans()
    }
}

fun add(){}
fun fade(){}
fun trans(){}
fun op(){}

假如声明了以上枚举类,然后when表达式来判断条件然后根据不同结果调用不同方法。编译成Java代码如下:

public static final void blend(@NotNull BlendMode blend) {
   Intrinsics.checkParameterIsNotNull(blend, "blend");
   switch(EnumsKt$WhenMappings.$EnumSwitchMapping$0[blend.ordinal()]) {
   case 1:
      op();
      break;
   case 2:
      fade();
      break;
   case 3:
      add();
      break;
   case 4:
      trans();
   }

}
...

// EnumsKt$WhenMappings.java
import kotlin.Metadata;

// $FF: synthetic class
@Metadata(
mv = {1, 1, 13},
bv = {1, 0, 3},
k = 3
)
public final class EnumsKt$WhenMappings {
// $FF: synthetic field
public static final int[] $EnumSwitchMapping$0 = new int[BlendMode.values().length];

static {
$EnumSwitchMapping$0[BlendMode.OPAQUE.ordinal()] = 1;
$EnumSwitchMapping$0[BlendMode.FADE.ordinal()] = 2;
$EnumSwitchMapping$0[BlendMode.ADD.ordinal()] = 3;
$EnumSwitchMapping$0[BlendMode.TRANSPARENT.ordinal()] = 4;
}
}

可以看出编译后的Java代码中的swtich还调用了生成枚举类中的数组。

这时由于二进制兼容性的原因,在枚举的序数值中,代码不能简单地应用这个值,因为它有可能会break(如果在项目中使用枚举,你更改了枚举的顺序,有可能破坏之前申请的顺序)。由此便有了EnumsKt$WhenMappings类中的静态代码块来执行映射操作。

如果我们在代码中有很多when语句和enum一起使用,就会生成很多类和数组。这会造成很大的内存和执行时间上的消耗。

一个好的解决方法就是使用R8,它会将编译后的代码优化为如下代码从而避免创建额外的类和数组:

public static final void blend(@NotNull BlendMode blend) {
Intrinsics.checkParameterIsNotNull(blend, "blend");
switch(blend.ordinal()) {
case 1:
op();
break;
case 2:
fade();
break;
case 3:
add();
break;
case 4:
trans();
}

}
点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像

Title - Artist
0:00