Better Buttered: A look at Butter Knife, a View "injection" library for Android

Better Buttered: A look at Butter Knife, a View "injection" library for Android

Code injection is usually something we try and avoid, but Jake Wharton of ActionBarSherlock fame (along with many other great open source Android libraries) is using injection for good.  With his open source “Butter Knife” library, you can use annotations to conveniently create commonly used code for Views in Android.  Let’s take a look at how to implement it into your project today.

Setup

  1. Add the library jar to your maven build or download from here
  2. Add jar to your Android project(also java build) and configure appropriate annotation settings.  See here for instructions for Eclipse and here for instructions for IntelliJ (if using external configuration, should just work without configuring).

 

Implementation

 

Once the project and environment are correctly configured you can start using the annotation techniques to add convenience injection to your code.  For instance if you would like to bind certain views you can use @InjectView annotation to bind view objects to their views (in addition the static inject function of ButterKnife must be called).  For example if there is an EditText view in the corresponding xml with id R.id.editText, you can bind it to an EditText variable named text by the following

@InjectView(R.id.editText) EditText text;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.inject(this);
 }

 

In addition the Butter Knife library allows us to conviently set onClick methods for views.  For instance if we had a Button buttonToast we could bind it and set an onClick listener with the code below

 

@InjectView(R.id.buttonAlert) Button buttonAlert;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.inject(this);
 }
 
@OnClick(R.id.buttonAlert)
public void alertClicked(View v){
    new AlertDialog.Builder(v.getContext())
        .setMessage(getFormattedMessge())
        .setNeutralButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
            }
        })
        .show();
}

 

In short, we can utilize Butter Knife to have cleaner and more understandable code and reduce development time but reducing redundant coding.  Find out more about Butter Knife on the official site or the Butter Knife GitHub repo.

 

The code below is a full example of an Activity (and its corresponding layout) showing the usefulness of Butter Knife

 

MainActivity.java

package com.tikal.butterknife.example;
 
import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RatingBar;
import android.widget.Toast;
 
public class MainActivity extends Activity {
               
    private static final String PRE_TEXT1 = "You have rated ";
    private static final String PRE_TEXT2 = " with ";
    private static final String PRE_TEXT3 = " stars";
               
    @InjectView(R.id.editText) EditText text;
    @InjectView(R.id.ratingBar) RatingBar rating;
    @InjectView(R.id.buttonAlert) Button buttonAlert;
    @InjectView(R.id.buttonToast) Button buttonToast;
               
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        ButterKnife.inject(this);
 
    }
 
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    @OnClick(R.id.buttonAlert)
    public void alertClicked(View v){
        new AlertDialog.Builder(v.getContext())
        .setMessage(getFormattedMessge())
        .setNeutralButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }})
        .show();
    }
   
    @OnClick(R.id.buttonToast)
    public void toastClicked(View v){
        Toast.makeText(v.getContext(), getFormattedMessge(), Toast.LENGTH_LONG).show();
    }
    private String getFormattedMessge() {
        return PRE_TEXT1 + text.getText().toString() + PRE_TEXT2 + rating.getRating() + PRE_TEXT3;
    }   
}

 

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
 
    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="20dp"
        android:layout_centerHorizontal="true"
        android:ems="10" >
 
        <requestFocus />
    </EditText>
   
      <RatingBar
        android:id="@+id/ratingBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editText"
        android:layout_centerHorizontal="true" />
 
    <Button
        android:id="@+id/buttonToast"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/ratingBar"
        android:text="Toast" />
 
 
 
    <Button
        android:id="@+id/buttonAlert"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/buttonToast"
        android:text="Alert" />
 
</RelativeLayout>
Thank you for your interest!

We will contact you as soon as possible.

Send us a message

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com