I'm trying to figure out the best way to do Android View Binding in Kotlin. It seems like there are a few of options out there:
findViewById
val button: Button by lazy { findViewById<Button>(R.id.button) }
Butterknife
https://github.com/JakeWharton/butterknife
@BindView(R.id.button) lateinit var button: Button
Kotlin Android Extensions
https://kotlinlang.org/docs/tutorials/android-plugin.html
import kotlinx.android.synthetic.main.activity_main.*
I'm pretty familiar with findViewById and Butterknife in java land, but what are the pros and cons of each view binding approach in Kotlin?
Does Kotlin Android Extensions play well with the RecyclerView + ViewHolder pattern?
Also how does Kotlin Android Extensions handle view binding for nested views via include
?
ex: For an Activity using activity_main.xml
, how would View custom1
be accessed?
activity_main.xml
<...> <include layout="@layout/custom" android:id="@+id/custom" /> </>
custom.xml
<...> <View android:id="@+id/custom1" ... /> <View android:id="@+id/custom2" ... /> </>
View binding is a feature that allows you to more easily write code that interacts with views. Once view binding is enabled in a module, it generates a binding class for each XML layout file present in that module.
Kotlin Android Extensions To solve the issue of writing useless code, JetBrains has created the Kotlin Android Extensions which have a number of features, but exist primarily to avoid the need for findViewById code. Using them is straightforward, you simply need to import kotlinx. android.
Implement Click Listeners for Buttons 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.
kotlin-android-extensions
is better for Kotlin
. ButterKnife is also good but kotlin-android-extensions
is a better and smart choice here.
Reason : Kotlin
uses synthetic
properties and those are called on demand using caching function
(Hence slight fast Activity/Fragment loading) while ButterKnife
binds all view at a time on ButterKnife.bind()
(that consumes slight more time). With Kotlin
you don't even need to use annotation for binding the views.
Yes it also plays good with RecyclerView + ViewHolder pattern, you just need to import kotlinx.android.synthetic.main.layout_main.view.*
(if layout_main.xml
is Activity/Fragment layout file name).
You do not need to do any extra effort for layout imported using include
. Just use id of imported views.
Have a look at following official documentation notes:
Kotlin Android Extensions is a plugin for the Kotlin compiler, and it does two things:
- Adds a hidden caching function and a field inside each Kotlin Activity. The method is pretty small so it doesn't increase the size of APK much.
Replaces each synthetic property call with a function call.
How this works is that when invoking a synthetic property, where the receiver is a Kotlin Activity/Fragment class that is in module sources, the caching function is invoked. For instance, given
class MyActivity : Activity() fun MyActivity.a() { this.textView.setText(“”) }
a hidden caching function is generated inside MyActivity, so we can use the caching mechanism.
However in the following case:
fun Activity.b() { this.textView.setText(“”) }
We wouldn't know if this function would be invoked on only Activities from our sources or on plain Java Activities also. As such, we don’t use caching there, even if MyActivity instance from the previous example is the receiver.
Link to above documentation page
I hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With