Waldo sessions now support scripting! – Learn more
App Development

An In-Depth Guide to Using ButterKnife With Kotlin

Pius Aboyi
Pius Aboyi
An In-Depth Guide to Using ButterKnife With Kotlin
August 31, 2021
5
min read

It’s safe to say every Android developer has used the findViewById() method at some point. The method is used for referencing views in Kotlin or the Java part of an app. However, writing findViewById() multiple times in a huge project can add extra boilerplate code. That’s where ButterKnife comes in: It replaces findViewById() with an annotation added to fields.

In this post, we’ll take a deep dive into how to use ButterKnife with Kotlin. To aid us with that, we’ll be walking through the process of adding the ButterKnife library to an example app.

Let’s start by taking a look at what ButterKnife is.

butterknife kotlin pull quote

What Is ButterKnife?

ButterKnife is an Android library that can eliminate the use of findViewById(). ButterKnife can also be described as a view and method binding library. That’s to say, it can be used to access views in Kotlin code and also connect Kotlin methods to views. For example, ButterKnife can eliminate the use of an inner-class to set click event listener to a button. This can be done using the @OnClick annotation.

Another use case for the ButterKnife library is access to resources like string. For example, ButterKnife’s @BindString annotation can be used to access string values from the string.xml resource file.

Later in the post, we’ll see some of ButterKnife’s annotations in action. However, before we continue, let’s compare ButterKnife to the findViewById() method.

Difference Between findViewById() and ButterKnife

To further explain ButterKnife, we’ll compare it side-by-side to the findViewById() method.

The traditional way of using findViewById() to reference a view is by creating a variable or field that’s initialized in the onCreate() method. The following code sample shows this:


val button1: Button = findViewById(R.id.button1)

ButterKnife, on the other hand, uses a BindView annotation. This annotation can be added to a field or variable. After that, ButterKnife is initialized using the ButterKnife.bind() method. The following code sample explains the above statement better:


val button1: Button = findViewById(R.id.button1)

Benefits of Using ButterKnife

There are many benefits of using ButterKnife in a Kotlin app. In this section, we’ll take a look at some of these benefits.

  1. It eliminates the use of findViewById(). With ButterKnife, you can save time and reduce the amount of boilerplate code associated with the findViewById() method.
  2. ButterKnife also eliminates the use of inner-class for click event listeners. Just annotate a method with @OnClick() and the library will handle the job of binding that method to the specified view.
  3. It provides access to resources like string using annotations (e.g., the @BindString() annotation).

How to Use ButterKnife in a Kotlin App

Now, we’ll walk through the steps for using ButterKnife with Kotlin. We’ll be building an example app that has three buttons. Our app will show three unique messages using Toast on the tap of each button. A screenshot of the app is shown below:

example app

Prerequisites

To follow along, it will be nice to have the following:

  1. Android Studio
  2. An Android Studio project (create a new project if you don’t already have one)
  3. Knowledge of Kotlin

With that said, let’s dive in to the steps.

1. Adding ButterKnife to Project

First, we’ll need to add the ButterKnife library to our project. To do that, add the following code to the app-level build.gradle file.

Add this under the plugin section:


plugins {
   id 'kotlin-kapt'
}

Then add this under dependencies:


dependencies {
   implementation 'com.jakewharton:butterknife:10.2.3'
   kapt 'com.jakewharton:butterknife-compiler:10.2.3'
}

When you’re done, click on the “Sync Now” button.

2. Adding Buttons to the App

As mentioned earlier, our example app will have three buttons. In this step, we’ll be adding the three buttons. Open the activity_main.xml file (located in the app/src/main/res/layout folder). Then add the buttons, using either layout designer or code view.

Change the IDs for the first, second, and third buttons to “button1,” “button2,” and “button3,” respectively. You can do this from the attribute pane.

adding buttons

Alternatively, you can add the following code under the parent layout to set up the three buttons without using the layout designer.


<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="Button1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Button3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/button3"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="Button2"
app:layout_constraintStart_toEndOf="@+id/button1"
app:layout_constraintTop_toTopOf="@+id/button1" />

3. Create and Annotate Fields

Now let’s create the fields that will represent our buttons. Open the MainActivity.kt file and add the following code just above the onCreate method.


@BindView(R.id.button1)
lateinit var button1: Button
@BindView(R.id.button2)
lateinit var button2: Button
@BindView(R.id.button3)
lateinit var button3: Button

At this point, we’ve successfully added ButterKnife to our app. That is, we’ve been able to make reference to views in our Kotlin code without using findViewById().

4. Initialize ButterKnife

The process of initializing ButterKnife does the actual work of binding the view in our app. This is done using the ButterKnife.bind() method.

Add the following code to MainActivity.kt inside the onCreate method. The code should be placed on a new line after setContentView().


ButterKnife.bind(this)

In the next step, we will code click event listeners for the three buttons in our example app.

5. Implement Click Listeners for Buttons

We’ll be adding a click listener event for each button on the app. We’ll do this using two options. The first is using setOnClickListener and a lambda function. Then, we will use ButterKnife’s @OnClick annotation.

Add the following code inside the onCreate() method. Place the code on a new line just below ButterKnife.bind().


button1.setOnClickListener {
Toast.makeText(this, "Button 1 pressed", Toast.LENGTH_SHORT).show()
}
button2.setOnClickListener {
Toast.makeText(this, "Button 2 pressed", Toast.LENGTH_SHORT).show()
}

In the above code, we left the implementation for button3 out. This is intentional, as we’ll be using the second option to implement it.

Next, we’ll create a new method to handle the click event for button3. To do this, add the following code directly inside the MainActivity class.


@OnClick(R.id.button3)
fun button3Pressed() {
Toast.makeText(this, "Button 3 pressed", Toast.LENGTH_SHORT).show()
}

The above code implements a method using the @OnClick() annotation we mentioned earlier. The resource ID for button3 is supplied as a parameter; hence, ButterKnife knows how to bind the method to button3.

6. Run the App

Connect your phone or start an instance of a virtual device, then hit the green play button to run the app. Once the app is running, tap on each button to see what happens. If you followed correctly, you should see the expected Toast message.

Testing ButterKnife Code

You can test views that use ButterKnife with Android’s instrumentation testing feature. However, you’ll need to include ButterKnife in your test dependencies. Once that’s done, you can use ButterKnife annotations in your test code.

You can test your Kotlin app that uses ButterKnife with the Espresso test library. The process is very similar to any normal Espresso test. With Espresso, you can find a view in an activity. It can also perform actions like click and scrolling using Kotlin code. The following code sample shows an Espresso test.


onView(withId(R.id.button3))
.perform(click())

The above code locates the view with resource ID “button3.” After that, it performs a click action automatically.

Finally, on testing, Waldo offers a no-code testing solution. With Waldo, you can test mobile apps without writing any extra test codes. There’s also no need to configure a test library. You can try this tool for free here.

butterknife kotlin pull quote

Conclusion

In this post, we learned about what ButterKnife is and how we can use it to eliminate findViewById() from a Kotlin app. Through our example app, we used the @BindView() annotation and the @OnClick() annotation to bind a view and a method, respectively.

Some years ago, ButterKnife was a lifesaver for many Android developers, as findViewById() adds much boilerplate code. However, ButterKnife has been deprecated and the developer of the library recommends using ViewBinding instead. Hence, it’s not recommended to use the library today.

Automated E2E tests for your mobile app

Waldo provides the best-in-class runtime for all your mobile testing needs.
Get true E2E testing in minutes, not months.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.