In this quick tip, you'll learn how to integrate the Butter Knife library in your projects to easily instantiate the views in your layout in your application's code.
Introduction
In every Android application, you have to use the findViewById()
method for each view in the layout that you want to use in your application's code. But as applications' designs get more complex layouts, the call to this method becomes repetitive and this is where the Butter Knife library comes in.
The Butter Knife library, developer and maintained by Jake Wharton (Square Inc.), has annotations that help developers to instantiate the views from our activity or fragment. It also has annotations to handle events like onClick()
, onLongClick()
, etc.
In the sample project of this tutorial, you can see a sample application with one activity and one fragment with an implementation using the Butter Knife library and a regular implementation. Let's explore the steps involved to integrate the Butter Knife library.
1. Using the Butter Knife Library
Step 1: Add the Dependency
Add the following dependency to the project's build.gradle file:
compile 'com.jakewharton:butterknife:6.1.0'
Next, synchronize your project with this file by pressing the synchronize button.
Step 2: Use the Annotations
In every activity or fragment, you have to remove, or comment out, every call of the findViewById()
method and add the @InjectView
annotation before the declaration of the variable, indicating the identifier of the view.
@InjectView(R.id.sample_textview) TextView sample_textview;
Step 3: Inject Views
In the onCreate()
method of the activity, before using any the views, call inject
on the Butterknife
object.
ButterKnife.inject(this);
If you are using fragments, you have to specify the source of the views in the onCreateView()
method as shown below.
View view = inflater.inflate(R.layout.sample_fragment, null); ButterKnife.inject(this, view);
You can now start using the views in your application's code. Butter Knife will handle the instantiation of every single view for you.
That is all you have to do to use the Butter Knife library in an activity or fragment.In the next section, I'll show you how to use the Butter Knife library for using list views.
2. Using the Butter Knife Library with List Views
The ListView
class is a special case to implement, because you instantiate the views inside an adapter. To integrate the Butter Knife library in a list view, you first have to create the custom layout for the items in the list view. I'm going to name mine list_view_item
and add the following layout:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:background="@android:color/white"><ImageView android:id="@+id/image_in_item" android:layout_width="100dp" android:layout_height="100dp"/><TextView android:id="@+id/textview_in_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:layout_toRightOf="@+id/image_in_item" android:layout_marginLeft="10dp"/></RelativeLayout>
In this simple layout, we're going to show an image and some text. Next, we need to create the adapter for the list view. Let's name it ListViewAdapter
.
public class ListViewAdapter extends BaseAdapter { LayoutInflater inflater; public ListViewAdapter(LayoutInflater inflater){ this.inflater = inflater; } @Override public int getCount() { return 5; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { return null; } static class ViewHolder{ public ViewHolder(View view){ } } }
Inside the adapter class, there's a static class called ViewHolder
to keep it in order. We're going to use this class to contain the views. Let's implement the ViewHolder
class as follows:
static class ViewHolder{ @InjectView(R.id.image_in_item) ImageView image; @InjectView(R.id.textview_in_item) TextView text; public ViewHolder(View view){ ButterKnife.inject(this, view); } }
All we have to do now is modify the getView()
method as follows:
public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; View view = inflater.inflate(R.layout.list_view_item, parent, false); holder = new ViewHolder(view); Picasso.with(inflater.getContext()) .load("http://lorempixel.com/200/200/sports/" + (position+1)) .into(holder.image); holder.text.setText("This is a text for the image number: "+position); return view; }
In this method, I'm inflating the custom layout inside the view
variable and use it to create an object of the ViewHolder
class. Note that we're using the Picasso
class to load remote images and populate the text view with some text. You may find the Picasso tutorial useful if you want to get more familiar with this library.
Don't forget to add the android.permission.Internet
permission in the Android manifest. If you don't, Picasso won't be able to connect to the web and load the remote images.
<uses-permission android:name="android.permission.INTERNET"/>
Finally, all you have to do is to instantiate the list view and attach the adapter. I'm going to do this inside a new activity, ListViewActivity
, as shown below. You can see an example of this implementation in the source files of this tutorial.
public class ListViewActivity extends ActionBarActivity { @InjectView(R.id.listView) ListView list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_view); ButterKnife.inject(this); list.setAdapter(new ListViewAdapter((LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE))); } }
3. Events
You can use Butter Knife's annotations for events too. Choose the annotation you want to use, according to the event you want to respond, and put it before the method you want to execute when the event happens.
@OnClick(R.id.sample_textview) public void showToastMessage(){ Toast.makeText(MainActivity.this, "This is a message from the activity", Toast.LENGTH_SHORT).show(); }
Conclusion
You can use Butter Knife inject()
method anywhere you would otherwise use the findViewById()
method to save time and avoid code repetition when you have to instantiate the views in the layout. Feel free to share this quick-tip if you found it helpful.