Android Dependency Assassin – Part 1: Butter Knife

A good knife man know his tools. The dagger is sharp and fierce while the butter knife is blunt and mellow. The sword is noble and swift while the Swiss army knife is handy and quick.

This post series will focus on reducing dependencies in Android application development using dependency injections frameworks. In the first post I’ll discuss the Butter Knife framework.

How many time have you found yourself writing over and over again the same boilerplate code for handling views in your UI classes (Activity or Fragment)? Something like that:

public class MyActivity extends Activity {
    TextView mDoSomethingView;
    ListView mDoSomethingElseView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
        ...
        mDoSomethingView = (TextView) findViewById(R.id.expandable_text);
        mDoSomethingView.setOnClickListener(new DoSomethingClickListener());
        ...
        mDoSomethingElseView = (ListView) findViewById(R.id.list_item);
        mDoSomethingElseView.setOnClickListener(new DoSomethingClickListener());
        ...
    }

    ...

    public class DoSomethingClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            // Hey, we're doing something!!!
            ...
        }
    }

    public class DoSomethingElseClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            // Hey, we're doing something else!!!
            ...
        }
    }

}

butterknifeButter knife enables you to “inject” the views and event callback or listener easily, without having to repeat the boilerplate code over and over again. Strictly speaking it will not actually inject the views, but will generate the boilerplate code for you behind the scene (this why we labeled it “injection” above). With butter knife the above sample will be reduced to the following:

public class MyActivity extends Activity {
    @InjectView(R.id.do_something) TextView mDoSomethingView;
    @InjectView(R.id.do_something_else) ListView mDoSomethingElseView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
        ButterKnife.inject(this);
        ...
    }

    ...

    @OnClick(R.id.do_something)
    public void imDoingSomething(TextView doer) {
        // Hey, we're doing something!!!
        ...
    }

    @OnClick(R.id.do_something_else)
    public void imDoingAnotherThing(ListView anotherDoer) {
        // Hey, we're doing something else!!!
        ...
    }


}

Much shorter, cleaner, readable and maintainable code.
Butter knife doesn’t use reflections. Instead it generate the boilerplate code in compile time and use it in run time, so it is fully debug-able and visible for you.

There are other view injection frameworks that will do what Butter knife is doing, such as RoboGuice, Android Annotations and more. Each has its pros and cons. Search the internet for comparisons (like this one, or this) and select the one that fits you best.

It is beyond the scope of this post to explain the benefits of dependency injection in software development, such as loose coupling, inversion of control and more. I encourage you to read more on this to understand the value of dependency injection.

In the next post I will discuss Dagger. Stay tuned.