What's new in Android Gradle Plugin 3.6
Tags: gradle, android, kotlin, build
Published: 2020-05-03 08:15:49

February 2020 was quite busy as we got 4.1 Canary release of Android Studio and Android Gradle Plugin (AGP), former 4.0 Canary was bumped to Beta and we got Stable version of 3.6.
[Android Gradle Plugin 3.6](https://developer.android.com/studio/releases/gradle-plugin#3-6-0) is the last version in 3.x series and the last version that will work with Gradle 5.x. In tradition of minor version updates, it brings few smaller enhancements, but this is time it has also a new Feature with big *F*.

# View Binding ([docs](https://developer.android.com/topic/libraries/view-binding))
What is the most famous function on Android?
Probably `View.findViewById()`. For various reasons developers are trying to avoid using it as much as possible.
There is a complete history of 3<sup>rd</sup> party libraries and frameworks like *Kotlin Android Extensions*, *Butter Knife* or *Android Annotations* that are trying to hide it behind a nicer API or annotations.
Also Google contributed to this list with *Data Binding* that also might serve as a replacement for binding `View`s defined in `layout.xml` and i.e. `Fragment`'s code, although it is maybe too heavy to be used for binding views only.
Maybe this was the reason why a new Google tool called `View Binding` was created.

### How does it work?
I won't go into details about what it does and how you can use it as we have already a plenty of other blog posts out there. 
But there is one technical detail I didn't find anywhere. From the docs:

> Once view binding is enabled in a module, it generates a binding class for each XML layout file present in that module.

**But who generates the code?**
- It cannot be an *Annotation Processor* as in comparison to *Data Binding*, *View Binding* is said to require no annotation processing for faster compilation.
- It cannot be *Kotlin Compiler Plugin* as *View Binding* works also for Java code.

I cannot find the answer anywhere, so I asked [the author](https://twitter.com/JakeWharton). It turns out that *View Binding* is a standalone tool that consist of three components.

### Code Generator

This is the actual *View Binding*'s engine.
It creates a [ViewBinder.kt](https://android.googlesource.com/platform/frameworks/data-binding/+/studio-master-dev/compilerCommon/src/main/kotlin/android/databinding/tool/writer/ViewBinder.kt) model for each layout in the project that requires a `*Binding` class to be generated.
Then there is [ViewBinderGenerateSource.kt](https://android.googlesource.com/platform/frameworks/data-binding/+/studio-master-dev/compilerCommon/src/main/kotlin/android/databinding/tool/writer/ViewBinderGenerateSource.kt) that takes the outputs of *Data Binding* XML layout parser and generates binding code using [JavaPoet](https://github.com/square/javapoet).

Artifact: `androidx.databinding:databinding-compiler-common` ([link](https://mvnrepository.com/artifact/androidx.databinding/databinding-compiler-common?repo=google))

### Build Hook

Code generation is invoked by Android Gradle Plugin during build. There is no much difference from how *Data Binding* is configured in [TaskManager.java](https://android.googlesource.com/platform/tools/base/+/studio-master-dev/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java#2400).

Artifact: `com.android.tools.build:gradle` ([link](https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google))

### Feature API

Last piece of the puzzle. *View Binding* has a tiny public API available to developers that consists of single class: [ViewBinding.java](https://android.googlesource.com/platform/frameworks/data-binding/+/studio-master-dev/extensions/viewbinding/src/main/java/androidx/viewbinding/ViewBinding.java). It serves as *marker interface* for all generated `*Binding` classes.

Artifact: `androidx.databinding:viewbinding` ([link](https://mvnrepository.com/artifact/androidx.databinding/viewbinding?repo=google))

**So, who generates the code?**

*Annotation Processors* tend to be problematic in terms of configuration and performance. 

*Kotlin Compiler Plugins* tend to be problematic to work with Java code (joke). 

*View Binding* tend to be tiny, simple and quick. It shows us that sometimes there is a better way how to solve a problem out of "standard tools". In this case, it is one's own code generator baked to the Android Gradle Plugin.

# Maven Publish plugin support ([docs](https://developer.android.com/studio/build/maven-publish-plugin))
Android Gradle Plugin 3.6 is not all about *View Binding*. If you are on a bigger project where dependencies are not shared as source code dependency but rather as compiled artifact dependency through artifact repository, it might be handy for you that AGP now supports Gradle's built-in [Maven Publish plugin](https://docs.gradle.org/current/userguide/publishing_maven.html).
For most of the projects this might save a few tens lines of Gradle publishing logic. 

# Enhancements on R class generation
`R` class serves as a static list of application resources known at compile time. As projects grow their `R` classes might easily get a few hundred thousand or even million lines of code that need to be compiled.

To optimize the build performance AGP 3.6 starts to generate the Java bytecode directly so you don't have compile it. It means that instead of `R.java` file in `build/generated` directory you can find `R.jar` file in `build/intermediates`.

Another change is that there is [only one `R` class generated per library module](https://developer.android.com/studio/releases/gradle-plugin#simplified-r-class). This forces you to have a unique package name for each project module. If you need help with this requirement, there is a [check introduced in AGP 3.4](https://dev.to/xsveda/what-s-new-in-android-gradle-plugin-3-4-3ki1#unique-package-names) that might serve you.

But what is the main reason that `R` classes are so big? By default, the module `R` class contains references to all module resources but also inherits all references from other module dependencies.
Example: Do you depend on *Material Design Components* library in your base module? Sorry, all of your project module `R` classes will contain few thousand of MDC fields. Bummer!
But there is a cure. AGP 3.3 introduces [not very well documented flag](https://twitter.com/JakeWharton/status/1032396242062594048). When you enabled it in `gradle.properties`:
```
android.namespacedRClass=true
```
it prevents references from dependencies being included in your module `R` class.
It also makes your module better isolated from architecture point of view as, unless you use explicitly import `R` class from other module, you can use only your module's resources. It prevents you to accidentally use a drawable or a string from another module.

# New default packaging tool ([docs](https://developer.android.com/studio/releases/gradle-plugin#zipflinger))
It is called *zipflinger* and you should not care unless you are doing some custom app packaging magic or so.
In such case, or in case you are somehow struggling with the new packaging tool, you can disable it in `gradle.properties`:
```
android.useNewApkCreator=false
```

# Conclusion
So that's it for Android Gradle Plugin 3.x series. Next time let's check what's new in Gradle 6.x and Android Gradle Plugin 4.x !!!