Last field at R2.java in ButterKnife

this is an Android extension : why do we need to use R2 instead of R with butterknife? and Link in R.java is not final

I understand that the R.java fields in a library project do not have a final modifier to protect value conflicts between library projects. However, ButterKnife restores the final modifier in R2 and uses it.

I think this concerns the collision problem, and the values ​​may collide, but there are no problems. How it works?

===

I am adding examples. There is one main project and one library project. The main project has com.main.R, and the library project has com.library.R.

  • In a collision:
    • com.main.R: public static final int example = 0x1234
    • com.library.R: public static int example = 0x1234

If the build tools do not recompile the library project, how can we avoid a collision between these values?

  1. When ButterKnife creates 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

com.library.R2 has a collision and even has a final modifier. Doesn't that create a problem? why?

thanks

+1
source share
2 answers

Although the final keyword was removed from the generated R.java class, since it had a negative impact on build performance, Butterknife uses only final for itself, so only Butterknife code needs to be recompiled every time a new identifier needs to be added. Good point - Butterknife uses annotations to make sure the return type is always correct.

From the doc:

In other words, constants are not final in a library design. The reason for this is simple: when combining multiple library projects, actual field values ​​(which must be unique) may collide. Prior to ADT 14, all fields were final, so as a result, all libraries had to recompile all of their resources and the corresponding Java code along with the main project whenever they were used. This was bad for performance, as it made the build very slow. It also prevented the distribution of library projects that did not include source code, limiting the scope of use of library projects.

The reason the fields are no longer final is that this means that library banks can be compiled once and reused in other projects. In addition to being able to distribute the binary version of library projects (coming to r15), this makes for much faster builds.

Imagine if R.java should still contain the final keyword, for each library module that you included in your Android project, recompilation should have been done since R.java will be used as the source code for Android and the library. Therefore, the last keyword has been deleted now. However, Butterknife still uses final because it doesn't care about collisions, but BindView annotations internally use those annotations like @IdRes , @StringRes , @DrawableRes , etc. Inside that provides type safety variables declared consistent.

+2
source

Next I explored. So,

  • Resource values ​​in library projects are reassigned when the main project is built
  • Final must be removed to use the reassigned values.
  • Values ​​in R2 are not reassigned, so conflicts can occur, but this is only a marker for Annotation. The actual value used when searching for views comes from R

Details here: https://battleshippark.wordpress.com/2018/02/12/butterknife-library-project-r2-final/

0
source

Source: https://habr.com/ru/post/1015135/


All Articles