ButterKnife R2作用和删除

在使用ButterKnife时library工程的注解会使用R2, 为什么使用R2而不是R呢?
ButterKnife R2作用和删除_第1张图片
ButterKnife R2作用和删除_第2张图片
如上图所示R.class中参数定义使用了final关键字, 即R.class里全部是常量; 而R2.class里全部是变量。
PS:Java语言在编译时常量内联, 即使用常量值替换参数;
Java 注解的属性和 switch-case 中的 case 表达式,必须使用常量或者值,否则会报语法错误。

@BindView(2131492938)
ImageView mBtnClose;
@BindView(2131493454)
TextView mTvHint;
@BindView(2131493452)

为什么Libraray中编译生成的R.class不是常量呢? 详见https://developer.android.com/studio/write/add-resources.html
为了避免library生成的值跟主工程重复, 编译时为library资源生成全局唯一的值。

ButterKnife利用 butterknife-gradle-plugin 拷贝一份 R.java 命名成 R2.java(参数名称/值完全相同,唯一区别是添加final关键字),即R2.java 里面的参数都是常量。这样就躲过了语法检查, library生成的最终字节码_ViewBinding.class仍然使用R$*.class

public class MessageListFragment_ViewBinding implements Unbinder {
  private MessageListFragment target;

  @UiThread
  public MessageListFragment_ViewBinding(MessageListFragment target, View source) {
    this.target = target;

    target.mTitleBar = Utils.findRequiredViewAsType(source, R.id.title_bar, "field 'mTitleBar'", MyTitleBar.class);
  }

  @Override
  @CallSuper
  public void unbind() {
    MessageListFragment target = this.target;
    if (target == null) throw new IllegalStateException("Bindings already cleared.");
    this.target = null;

    target.mTitleBar = null;
  }
}

ButterKnife生成的R2.java和安卓生成的R.java在编译后产生R$.class和R2$.class, 可以使用gradle插件删除R2相关类(除stylable), 并替换字节码中R.*为常量值后删除R相关类; 从而有效减少dex文件的参数、类个数。
ButterKnife R2作用和删除_第3张图片

Android apk瘦身最佳实践(一):去除R.class
删除R.java的插件
AOP 最后一块拼图 | AST 抽象语法树 —— 最轻量级的AOP方法

你可能感兴趣的:(Android)