Integrating ButterKnife 8.4.0 for Android View Injection
ButterKnife streamlines Android UI development by generating boilerplate-free view lookups and event handlers at compile time. The framework eliminates explicit findViewById() calls and anonymous inner classes for listeners, resulting in cleaner activity and fragment structures. Because injection happens during compilation, there is negligible impact on application performance.
Gradle Setup
Version 8.4.0 relies on the android-apt plugin. Configure the project root build.gradle:
buildscript {
repositories { jcenter() }
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
allprojects {
repositories { jcenter() }
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Apply the plugin and declare libraries in the module build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'android-apt'
android {
compileSdkVersion 24
defaultConfig {
minSdkVersion 14
targetSdkVersion 24
}
}
dependencies {
compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'
}
Field Binding
Attach the @BindView annotation to fields referencing UI components. The field scope must remain package-private, protected, or public; static and private modifiers trigger compilation errors. Initialize injections with in the lifecycle phase immediately following layout inflation.
package com.dev.sample.ui;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.action_submit)
Button submitAction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
submitAction.setText("Process Request");
}
}
Multiple View Collections
The @BindViews annotation maps a group of identifiers to a List<T>. This simplifies uniform styling or property updates across sibling elements.
package com.dev.sample.ui;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import java.util.List;
import butterknife.BindViews;
import butterknife.ButterKnife;
public class DashboardActivity extends AppCompatActivity {
@BindViews({ R.id.header_label, R.id.sub_title, R.id.footer_status })
List<TextView> statusLabels;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
ButterKnife.bind(this);
for (int i = 0; i < statusLabels.size(); i++) {
statusLabels.get(i).setText("Status Node " + (i + 1));
}
}
}
Fragment Lifecycle Handling
Fragments require a two-argument bind call passing the inflated view hierarchy. Injection should ocurr after inflate() but before returning the view reference.
package com.dev.sample.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MediaPanel extends Fragment {
@BindView(R.id.media_display)
ImageView mediaView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
View baseView = inflater.inflate(R.layout.fragment_media, container, false);
ButterKnife.bind(this, baseView);
mediaView.setImageResource(R.drawable.placeholder_image);
return baseView;
}
}
Resource Field Injection
External resources can be bound directly to member variables using specialized annotations.
package com.dev.sample.config;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;
import android.widget.RatingBar;
import butterknife.*;
public class SettingsScreen extends AppCompatActivity {
@BindView(R.id.input_field) EditText userField;
@BindView(R.id.rating_control) RatingBar scoreBar;
@BindString(R.string.greeting_msg) String welcomeText;
@BindArray(R.array.region_options) String[] locationData;
@BindBitmap(R.drawable.logo_icon) Bitmap companyLogo;
@BindColor(R.color.primary_theme) int accentColor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
ButterKnife.bind(this);
userField.setHint(welcomeText);
scoreBar.setProgress(5);
// companyLogo and accentColor are now valid references
}
}
Event Delegation via Annotations
Replace listener implementations with direct method annotations. Return types and signatures are strictly enforced by the compiler.
package com.dev.sample.interactions;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnLongClick;
public class ActionHub extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hub);
ButterKnife.bind(this);
}
@OnClick(R.id.trigger_button)
public void executePrimaryAction() {
Toast.makeText(this, "Short tap registered", Toast.LENGTH_SHORT).show();
}
@OnLongClick(R.id.trigger_button)
public boolean handleExtendedInteraction() {
Toast.makeText(this, "Hold gesture detected", Toast.LENGTH_LONG).show();
return true; // Consumes the event
}
}
Automated Code Generation
The Zelezny plugin accelerates setup by scanning layout XML files. Position the text cursor on the setContentView(R.layout.your_layout) statemant within your Activity. Invoke the generation shortcut, select the target views from the modal dialog, and confirm. The plugin automatically produces the necessary @BindView declarations and ButterKnife.bind(this) invocation. For adapter architectures, enable the CreateViewHolder option during selection to inject @BindView directly into custom ViewHolder classes, optimizing recycler list performance.