Creating applications in Android can sometimes be a very repetitive task. As a developer, you have to deal with redundant codes to find Views, to use View Holder pattern for your lists, to install your event listeners, … Write this kind of boilerplate code is bad for your productivity. A great solution would be to find a way to remove this boilerplate code. But how ? Actually, the best solution is to use Butter Knife, a lightweight library letting you mainly inject views into Android components via some annotations.

butterknife

1. Installation and configuration

Developed by Jake Wharton from Square, which is well known in the Android universe, Butter Knife is now in version 7.0.1. First step is to install Butter Knife library to use it in your Android project. To achieve that, you must add the Buffer Knife dependency in your build.gradle file :

compile 'com.jakewharton:butterknife:7.0.1'


You must also be sure to suppress the following lint warning in your build.gradle :

lintOptions {
  disable 'InvalidPackage'
}

 

2. Inject Views directly in your Android components

Main feature offered by Butter Knife is View injection directly in Android components. This feature is offered via @Bind annotation. Imagine you have a layout with several TextView elements. In your Activity, you have to use the following code :


public class MyActivity extends Activity {
 @Bind(R.id.title1) TextView title1;
 @Bind(R.id.title2) TextView title2;
 @Bind(R.id.title3) TextView title3;

 @Override public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.myactivity_layout);
 ButterKnife.bind(this);
 // …
 }
}

Here, you have just to annotate your fields with @Bind and a view ID to help Buffer Knife to find and automatically cast the corresponding view in your layout. Instead of slow reflection, Buffer Knife is going to generate the code that will perform the view look-ups. When you call the static method bind, the binding is made.

If you work in a non-activity context, like a fragment, you have to use the following code in the onCreateView method of the fragment :


public class MyFragment extends Fragment {
   @Bind(R.id.button1) Button button1;
   @Bind(R.id.button2) Button button2;

   @Override public View onCreateView(LayoutInflater inflater, ViewGroup vgroup, Bundle savedInstanceState) {
      View view = inflater.inflate(R.layout.fancy_fragment, vgroup, false);
      ButterKnife.bind(this, view);
      // ...
      return view;
   }
}

 

3. Inject Resources easily in your Android components

Even better, Buffer Knife lets you to bind resources directly via some other annotations like @BindColor, @BindDimen, @BindDrawable, @BindString, … You have always to put the correct ID in parameter of your annotation :

@BindString(R.string.my_string) String myString;
@BindDrawable(R.drawable.my_drawable) Drawable myDrawable;

 

4. Using the power of Buffer Knife with List Views

Because you must instantiate the views inside an adapter, the ListView class can be considered as a special case to implement. When you want integrate Buffer Knife in a list view, you must first create the custom layout for your items :


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">
  <TextView
   android:id="@+id/title1"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:textSize="16sp"/>

  <TextView
   android:id="@+id/title2"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:textSize="16sp"/>
</LinearLayout>

Then, you can simplify your View Holder pattern usage in the list adapter :


public class MyAdapter extends BaseAdapter {
 @Override public View getView(int position, View view, ViewGroup parent) {
  ViewHolder holder;

  if (view != null) {
    holder = (ViewHolder) view.getTag();
  } else {
    view = inflater.inflate(R.layout.my_items_layout, parent, false);
    holder = new ViewHolder(view);
    view.setTag(holder);
  }

  holder.title1.setText("Sylvain");
  holder.title2.setText("Saurel");

  return view;
 }

 static class ViewHolder {
  @Bind(R.id.title1) TextView title1;
  @Bind(R.id.title2) TextView title2;

  public ViewHolder(View view) {
    ButterKnife.bind(this, view);
  }
 }
}

 

5. Bind your Event Listeners

You can automatically bind your Event Listeners thanks to @OnClick annotation :


@OnClick(R.id.my_btn)
public void showToastMessage(){
  Toast.makeText(MainActivity.this, "Click on my Button !", Toast.LENGTH_SHORT).show();
}

 

6. Bonus

Besides the previous core features presented, Butter Knife has also some other bonus options. For example, you can use it to group multiple views in a List. Thus, you can bind a list of TextView in a List :


@Bind({ R.id.title1, R.id.title2, R.id.title3 })
List<TextView> titles;

You can also apply an Android Property to all the elements of a List with the static apply method of BufferKnife object :


ButterKnife.apply(titles, View.ALPHA, 0.0f);

Finally, don’t forget to reset your binding when you have finished your activity or your fragment with :


BufferKnife.unbind(this);

 

7. Conclusion

Buffer Knife is a simple and powerful library that will make your like easier. Quickly, it will be your essential tool during your Android developments to remove boilerplate code.