ButterKnife中R2.java中的最后一个字段

时间:2018-02-02 06:44:33

标签: android butterknife

这是Android: Why do we need to use R2 instead of R with butterknife?Reference in R.java not final

的扩展

我知道库项目中R.java的字段没有最终修饰符来保护库项目之间的价值冲突。但ButterKnife在R2中恢复了最终修饰符并使用它。

我认为这涉及到碰撞问题并且值可能会发生碰撞,但没有问题。它是如何工作的?

===

我添加了示例。 有一个主要项目和一个图书馆项目。主项目有com.main.R,库项目有com.library.R。

  1. 发生碰撞时:
    • com.main.R:public static final int example = 0x1234
    • com.library.R:public static int example = 0x1234
  2. 如果构建工具不重新编译库项目,我们如何避免这些值之间的冲突?

    1. 当ButterKnife创建R2时
      • com.main.R:public static final int example = 0x1234
      • com.library.R:public static int example = 0x1234
      • com.library.R2:public static final int example = 0x1234
    2. com.library.R2发生了碰撞,甚至还有一个最终修饰符。它不会产生问题吗?为什么呢?

      谢谢

2 个答案:

答案 0 :(得分:2)

虽然已从final生成的类中删除了R.java关键字,因为它对构建性能造成了负面影响,但Butterknife仅使用final,这就是为什么只有Butterknife代码每次添加新ID时都需要重新编译。好点是Butterknife使用注释来确保我们返回的类型始终是正确的。

来自doc:

  

换句话说,常量在库项目中不是最终的。原因很简单:当组合多个库项目时,字段的实际值(必须是唯一的)可能会发生冲突。在ADT 14之前,所有字段都是最终字段,因此,所有库都必须在使用它们时将所有资源和相关Java代码与主项目一起重新编译。    这对性能不利,因为它使构建非常慢。它还阻止了分发没有包含源代码的库项目,限制了库项目的使用范围。

     

字段不再是最终的原因是它意味着库jar可以编译一次并直接在其他项目中重用。除了允许分发二进制版本的库项目(来自r15),这样可以更快地构建。

想象一下如果R.java仍然应该包含final关键字,那么对于您在android项目中包含的每个库模块,需要重新编译,因为那时将使用R.java通过Android源代码和库。因此,最终关键字已被删除。但是,Butterknife仍然使用final因为它不关心冲突,但BindView注释在内部使用那些类型注释,如@IdRes@StringRes,{{ 1}}等内部确保声明一致的变量的类型安全。

答案 1 :(得分:0)

我进一步调查了。总之,

  • 在构建主项目时重新分配库项目中的资源值
  • 需要删除“最终”以使用重新分配的值
  • R2中的值未重新分配,因此可能会发生冲突,但它只是Annotation的标记。查找视图时使用的实际值来自R

详细信息如下: https://battleshippark.wordpress.com/2018/02/12/butterknife-library-project-r2-final/