Using the Butterknife library for view injection in Android. This tutorial explains the usage of the butterknife library to inject views into Android application.
1. Butterknife
Butterknife is a light weight library to inject views into Android components. It uses annotation processing.
The @BindView
annotation allow to inject views and performs the cast to the correct type for you.
The @@OnClick(R.id.yourid)
annotation allows to add OnClickListener to a view.
You can optional define the method parameter of the view in case you want it injected.
Butterknife includes also findById
methods which simplify code that still has to find views on a View, Activity, or Dialog.
It uses generics to infer the return type and automatically performs the cast.
import static butterknife.ButterKnife.findById;
....
View view = LayoutInflater.from(context).inflate(R.layout.thing, null);
TextView firstName = findById(view, R.id.first_name);
TextView lastName = findById(view, R.id.last_name);
ImageView photo = findById(view, R.id.photo);
You can also bind to fragments.
Butterknife also allows to unbind again, via the Unbinder
object.
public class YourFragment extends Fragment {
@BindView(R.id.button1) Button button1;
@BindView(R.id.button2) Button button2;
private Unbinder unbinder;
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
// TODO Use fields...
return view;
}
@Override public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}
Annotated attributes and methods cannot be private, as ButterKnife needs to be able to access them from a separate class.
2. How does Butterknife work
Butterknife uses annotation processing to generated modified Java classes based on your annotations. Annotation processing is a tool build in javac for scanning and processing annotations at compile time.
You can define custom annotations and a custom processor to handle them. These annotations are scanned and processed at compile time. The annotation processor does not change the exiting input class but it generates a new Java class. This generated Java code is compiled again as a regular Java class.
The Butterknife annotation processor scans all Java classes looking for the Butterknife annotations. If a class contains these annotations, it generates a new class based on the <original_class>__ViewBinding schema.
Here is the generate class from our example.
// Generated code from Butter Knife. Do not modify!
package com.vogella.android.butterknifeexample;
import android.support.annotation.CallSuper;
import android.support.annotation.UiThread;
import android.view.View;
import android.widget.TextView;
import butterknife.Unbinder;
import butterknife.internal.DebouncingOnClickListener;
import butterknife.internal.Utils;
import java.lang.IllegalStateException;
import java.lang.Override;
public class MainActivity_ViewBinding implements Unbinder {
private MainActivity target;
private View view2131165194;
@UiThread
public MainActivity_ViewBinding(MainActivity target) {
this(target, target.getWindow().getDecorView());
}
@UiThread
public MainActivity_ViewBinding(final MainActivity target, View source) {
this.target = target;
View view;
target.title = Utils.findRequiredViewAsType(source, R.id.textView, "field 'title'", TextView.class);
view = Utils.findRequiredView(source, R.id.button, "method 'submit'");
view2131165194 = view;
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.submit();
}
});
}
@Override
@CallSuper
public void unbind() {
MainActivity target = this.target;
if (target == null) throw new IllegalStateException("Bindings already cleared.");
this.target = null;
target.title = null;
view2131165194.setOnClickListener(null);
view2131165194 = null;
}
}
Once you call ButterKnife.bind(this)
, this will call into the generated constructor and perform the view injections and listener registration.
3. Exercise: Using Butterknife in your Android project
3.1. Create project
Create a new Android project with the package com.vogella.android.usinglibs
.
Add a text view with the @+id/textView
to it and a button to the existing layout with the @+id/button
ID.
3.2. Add Butterknife to your Gradle build configuration
Add the com.jakewharton:butterknife
in its latest version as compile dependency build.gradle
file.
apply plugin: 'com.android.application'
android {
...
}
dependencies {
...
implementation 'com.jakewharton:butterknife:8.5.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
}
3.3. Use view injection in your Android activity
Use @BindView
, @OnClick
and ButterKnife.bind
to get the views injected.
The following shows a possible solution.
package com.vogella.android.usinglibs;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends Activity {
@BindView(R.id.textView)
TextView title;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
title.setText("Hello from Butterknife");
}
@OnClick(R.id.button)
public void submit() {
Toast.makeText(MainActivity.this,
"Hello from Butterknife OnClick annotation", Toast.LENGTH_SHORT).show();
}
}
3.4. Validate setup
Run your application and ensure that the TextView
gets injected and the button event is fired, if you click the button.
4. Links and Literature
4.2. vogella Java example code
If you need more assistance we offer Online Training and Onsite training as well as consulting