Butterknife - A viewbinding tool for Android

Are you tired of writing findViewById(R.id.view) everywhere in your app where you are dealing with views?

There is a tool by Jake Wharton at Square, called Butterknife that uses annotation processing to generate this boilerplate code for you.

It can do field and method binding for your views, which can save you a lot of typing, and make your code a tad cleaner.

Installation

This is the easiest part ever.

Add Butterknife to your app with Gradle. Add this to your dependency list in your apps build.gradle:

compile 'com.jakewharton:butterknife:6.1.0'  

And then sync gradle to download and install it. Done.

General usage

A simple example can look like:

class MainActivity extends Activity {  
  @InjectView(R.id.title) TextView title;
  @InjectView(R.id.button) Button button;

  @Override 
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);
    ButterKnife.inject(this);
    //Now you can use the "injected" views.
  }
}

If you want to hook up a click listener to your button, you can easily do that with Butterknife annotations:

@OnClick(R.id.button) 
void buttonClick() {  
    //...
}

Then you don't even need the line that injects the button (since it's not being used elsewhere): @InjectView(R.id.button) Button button;.

Injecting views in fragments

If the view you are injecting is inflated, you can pass it as an argument to Butterknife.inject(), to specify where it should bind the views.

An example fragment might look like this:

public class SomeFragment extends Fragment {

    @InjectView(R.id.someTextView) 
    TextView someTextView;

    @Override
    public View onCreateView(LayoutInflater inflater,
            ViewGroup container, Bundle savedInstanceState) {

        ViewGroup rootView = (ViewGroup) inflater
                .inflate(R.layout.fragment_somelayout, container, false);

        ButterKnife.inject(this, rootView);

        //Use the TextView:
        someTextView.setVisibility(View.VISIBLE);
        return rootView;
    }

    @OnClick({ R.id.imageView, R.id.someTextView })
    public void doSomething() {
        //Do something when imageView or someTextView is clicked.
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        //Set views to null:
        ButterKnife.reset(this);
    }
}

Here, a TextView is bound to a field variable, and both the TextView and an imageView is assigned a click listener.

Using Butterknife in the viewholder pattern

You can use Butterknife to bind views in ViewHolder classes. Take for example this ArrayAdapter from my List dialog example:

If you compare this ArrayAdapter that uses Butterknife, to the original one that does not, you will see that it does simplify the code a little bit. This is a small example, but larger classes would benefit even more.

This is without Butterknife:

You can read more about the Butterknife tool in their docs, but it's really a straigh forward tool to use.

comments powered by Disqus