Skip to content

Library Modules

Nathanael Silverman edited this page Oct 24, 2018 · 3 revisions

Paris can be used in library modules and in projects with multiple modules. See configuration instructions below.

Paris Classes

Each module generates a Paris class in its root package. Just like with the R class, make sure to import the Paris class associated with the current module. This only applies if you're using Java. In Kotlin, calls to Paris have been replaced with the style extension function which is always imported from the same package: import com.airbnb.paris.extensions.style.

R Values and Annotations

To use Paris in a library you'll need to add the Butter Knife Gradle plugin to your buildscript:

buildscript {
  repositories {
    mavenCentral()
   }
  dependencies {
    classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1'
  }
}

Then apply it in your module:

apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'

Now make sure you use R2 instead of R inside all Paris annotations:

@Styleable("MyHeader")
class MyHeader(…) : ViewGroup(…) {

    @StyleableChild(R2.styleable.MyHeader_titleStyle)
    internal val title: TextView …
    
    @Attr(R2.styleable.MyHeader_title)
    fun setTitle(title: String?) {
        …
    }

    …
}
Click to see the example in Java.
@Styleable("MyHeader")
public class MyHeader extends ViewGroup {

    @StyleableField(R2.styleable.MyHeader_titleStyle)
    TextView title;
    
    @Attr(R2.styleable.MyHeader_title)
    public void setTitle(String title) {
        …
    }

    …
}

Why is Paris using a Butter Knife plugin?

First, why is a plugin even necessary? Every Android module generates an R class aggregating its own resource IDs with that of its dependencies. As such, it's the application module, the last one to be compiled, that sets the final resource IDs. Because the R fields generated by library modules aren't final—literally, not final—Java doesn't allow them to be used as annotation values.

In the face of this the Butter Knife folks came up with an ingenious solution. The plugin generates an R2 class with final fields for each module such that they can be used in annotations. The annotation processor then works back from R2 to access the real R values.

In a nutshell the Butter Knife plugin is part of a generic solution for using R values within annotations and so we decided to depend on it rather than reinvent the wheel.