Remove your boilerplate code in Android with Butter Knife
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.
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.
Leave a Reply
You must be logged in to post a comment.