Si has desarrollado o estas desarrollando una aplicación en Android, Debes estar muy familiarizado con esto:

TextView textView = (TextView) findViewById(R.id.text_view);

Esto es demasiado tedioso, peor aun si vienes de desarrollo de aplicaciones Windows con .NET.

Aunque felizmente aparir de API 26 o posterior ya no es necesario hacer el Cast

TextView textView = findViewById(R.id.text_view);

Esto se debe a que el tipo de resultado se infiere del objeto asignado. Muy elegante ¿verdad? ¿Pero quieres dar un paso más?

ButterKnife es probablemente la biblioteca que no te debes perder.

Añade a tu proyecto

dependencies {
    ...
    compile 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

El uso es muy sencillo, Simplemente tenemos que declarar nuestras vistas como siempre lo hacemos pero antes debemos agregar la anotación @BindView

Adicionalmente en el método onCreate() debemos incluir la sentencia ButterKnife.bind(this) quedaría como el siguiente :

class ExampleActivity extends Activity {
  @BindView(R.id.title) 
  TextView title;

  @Override 
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.bind(this);
  }
  @OnClick(R.id.submit)
  public void doSomething() { }
}

Cuál es la magia detrás de esta librería ?

Como trabaja ?

ButterKnife auntogenera un clase auxiliar con el nombre de la clase actual. En nuestro ejemplo es ExampleActivity$$ViewBinder que tiene el mismo nombre de paquete pero debajo de la carpeta de compilación.

La clase auxiliar quedaría algo como este:

public class ExampleActivity$$ViewBinder<T extends ExampleActivity> implements ViewBinder<T> {
  @Override 
  public void bind(final Finder finder, final T target, Object source) {
    View view;
    view = finder.findRequiredView(source, 2131297613, "field 'titleView'");
    target.titleView = finder.castView(view, 2131297613, "field 'titleView'");
    view = finder.findRequiredView(source, 2131296418, "method 'doSomething'");
    view.setOnClickListener(
      new butterknife.internal.DebouncingOnClickListener() {
        @Override 
        public void doClick(android.view.View p0) {
          target.doSomething();
        }
      });
  }

  @Override 
  public void unbind(T target) {
    target.titleView = null;
  }
}

Otros casos de Uso

Ademas de BindView  Hay muchas otras anotaciones útiles como: BindBool, BindColor, BindDimenBindDrawableBindIntBindString que enlaza a cada recurso correspondiente, Por ultimo, no menos importante, debes conocer a @OnClick(R.id.submit) que ejecuta el evento click de una vista.

Limpiando Código

Podemos mejor nuestro código aun más, para hacer uso de la librería en cada activity debemos llamar a ButterKnife.bind(this) para evitar hacer esto.

1. Crear una “BaseActivity” abstracta

public abstract class BaseActivity extendes AppCompatActivity{
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        Butterknife.bind(this);
    }

    public abstract int getLayoutId();
}

2. Nuestra activity extiende de BaseActivity

public class MainActivity extendes BaseActivity{
    
    @BindView(R.id.tex_view_1)
    TextView textView1;

    @BindView(R.id.tex_view_2)
    TextView textView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public int getLayoutId(){
        return R.layout.activity_main;
    }
}

Si hacemos que todas nuestras activities hereden de BaseActivity no tendremos que hacer el bind y encima empezamos a limpiar aun más el proyecto.