Need help with artist?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

207 Stars 16 Forks Apache License 2.0 106 Commits 5 Opened issues


An artist creates views. Artist is a Gradle plugin that codegens a base set of Android Views.

Services available


Need anything else?

Contributors list

Artist Build Status

As Android apps grow, providing common features and consistent functionality across Views becomes challenging. Typically, this results in copy-pasting features across views, monolithic classes, or complicated inheritance trees. Artist is a highly-extensible platform for creating and maintaining an app’s base set of Android views.


Artist is a Gradle plugin written in Kotlin that generates a base set of Android

s. Artist-generated views are created using a stencil and trait system. Each view type is declared with a single stencil, which is comprised of a set of traits. All of this comes together to create an easily maintainable system of stencils and traits.

Stencils: A

defines a View class to be generated. Each
has some properties that can be configured and declares a set of traits they exhibit.

Traits: A

defines the new functionality that should be added to a view. It is a hook into the
’s codegen process that is called during each
’s generation. It is responsible for generating the code that implements
's functionality. This could be used to do things like add automatic view analytics to every view or add first-party support for RxBinding APIs (clicks, attach events, visibility changes, etc.) on all your views.

A simple

that adds visibility helper methods would look like:
class VisibilityTrait : JavaTrait {
  override fun generateFor(type: Builder, initMethod: MethodSpec.Builder, rClass: ClassName, baseType: String) {
    arrayOf("visible", "invisible", "gone")
        .forEach { type.addMethod(createVisibilityConvenienceMethod(it)) }

private fun createVisibilityConvenienceMethod(type: String): MethodSpec { return MethodSpec.methodBuilder("is${type.capitalize()}") .addModifiers(Modifier.PUBLIC) .returns(TypeName.BOOLEAN) .addStatement("return getVisibility() == $T.${type.toUpperCase()}", TypeNames.Android.View) .build() } }

A simple

to generate a
with visibility helper methods would look like:
class SwitchStencil : JavaViewStencil(
    extendedType = "",
    constructorCount = 3,
    defaultAttrRes = "switchStyle",
    addedTraits = {

override fun name() = "MySwitch" }

Finally leaving you with a generated view like this:

public class MySwitch extends SwitchCompat {
  // Constructors

// protected init method - provided in every stencil

public boolean isVisible() { return getVisibility() == View.VISIBLE; }

public boolean isGone() { return getVisibility() == View.GONE; }

public boolean isInvisible() { return getVisibility() == View.INVISIBLE; } }

This may look like a lot of boilerplate for simple helpers, but it scales quite well when you want to have these methods on all your base views.


Common Façade

Everything is behind the façade of commonly named classes, basically "[YOUR_PREFIX]ViewName". This allows you to push as much functionality as you want behind them whilst not changing the front facing entry point. Things we can push behind them include new functionality, other base classes, framework bug fixes, etc.

Sane, simple maintainability

The stencil and trait system ensures that base views are defined in one place and that extra functionality is divided up into single-focus traits.

Reactive Semantics

Artist-generated views can have RxBinding APIs as first class citizens in their public APIs. In a increasingly reactive world, this gracefully bridges common UI listener interactions to RxJava streams. This can optionally be brought in via the



Artist-generated views have deep internal knowledge of their internal state and interactions. This gives you flexibility to do a number of interesting, contextual actions under the hood.

Automatic Instrumentation: Artist-generated views know when they're being attached, changed to visible, clicked, etc. This allows you to do automatic instrumentation of impressions and taps in views when they occur, provided the developer has provided an ID. You can also detect and signal a developer if an ID is missing where there should be one.

Accessibility: This intelligence gives you enough insight into the state of the view hierarchy to make accessibility a first class citizen in the daily development cycle. Artist-generated views can intelligently infer if there are content description errors associated with them, and signal them to developers in the apps.

For more examples of things you can do with Artist, check out the Recipes wiki page.


Create the Provider module

  • Create a new plain Java/Kotlin module (non-Android)
  • Add Artist dependencies (API, Traits, Traits-Rx)

Implement the Stencil Provider

  • Create a class that implements
  • Annotate your class with

Implement Custom Traits (Optional)

  • If you have custom traits, then create classes that implement
  • Annotate those classes with

Add Provider module to Plugin Classpath

Option #1

If your provider module is in it's own project, then you can add the JAR to the buildscript classpath in your main project's root

buildscript {
  dependencies {

Option #2

Otherwise, if your provider module is in your primary project, then in order for Artist to find the classes on the plugin classpath during code generation, we must leverage Gradle's

. We use this project within your project to build the classes that will be added to the plugin classpath. This will run before your primary project is built.
  • Create a dir at root of project named
  • Navigate to
    and add a relative symlink to the provider module
    cd $PROJECT_ROOT/buildSrc; ln -s ../path/to/provider/module/root custom-artist-providers
  • Create a
    and add
    include :custom-artist-providers
  • Update the
    for the
    project to ensure that the
    module is added the buildScript classpath so it is available to the Artist plugin:
subprojects { subproject ->
    if (subproject.buildFile.exists()) {
        repositories {

    rootProject.dependencies {
        runtime project(path)
subproject.afterEvaluate {
    // Disable useless tasks in buildSrc
    if (subproject.plugins.hasPlugin("kotlin")) {
        subproject.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
            kotlinOptions.suppressWarnings = true

    subproject.tasks.findAll {"test") ||
  "lint") ||
  "checkstyle") }.each {
        it.enabled = false


Use the Generated Views

The generated views will be added to the library's source files. They can then be consumed as regular views. To add even more consistency, you can write a lint rule or ErrorProne check to ensure that all

subclasses use your Artist-generated views.

Further examples

The set of

s that Artist should process are provided via the
. The sample's ViewStencilProvider would configure Artist to generate these Views.


Artist Plugin Maven Central

classpath 'com.uber.artist:artist:0.4.7'

Artist API Maven Central

classpath 'com.uber.artist:artist-api:0.4.7'

Artist Traits Maven Central

classpath 'com.uber.artist:artist-traits:0.4.7'

Artist Rx Traits Maven Central

classpath 'com.uber.artist:artist-traits-rx:0.4.7'


Copyright (C) 2017 Uber Technologies

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.