Recently, I started exploring the plugins packed into Kotlin. Truth be told, it has been an amazing experience incorporating Kotlin into my development. Although, the entire code base of my projects ain’t kotlin yet but I have been able to see a noteworthy refinement in my code structure so far.
Kotlin Android Extensions plugin was developed by the Kotlin team to make Android development easier. For now this plugin only includes a view binder. The plugin automatically generates a set of properties that give direct access to all the views in the XML. This way we don’t need to explicitly find all the views in the layout before starting using them.
At this point, we must be careful when choosing names for our views because they will be an important part of our classes. The type of these properties is also taken from the XML, so there is no need to do any extra castings. One of the advantages of Kotlin Android Extensions is that it doesn’t add any extra
libraries to our code. It just consists of a plugin that generates the code it needs to work only when it’s required, just by using the standard Kotlin library.
Ways to Implement Kotlin Android Extensions
You don’t need any sophisticated way of implementing Android Extension in your project. If you already have a java project and would like to use this plugin for all your view binding in Activities and Fragments.
Open your app build.gradle and add this:
apply plugin: 'kotlin-android-extensions'
You don’t have to do this if you are creating a Kotlin project from scratch. All the Kotlin dependencies will be automatically added to app gradle file.
Android Extensions for Activities or Fragments
This is the regular way to use it. The views can be directly accessed as if they were properties of the activity or fragment. Note that the names of the properties are the ids of the views in the XML. The import we need to use will start with kotlin.android.synthetic plus the name of the XML we want to bind to the activity. We also have to specify the build variant. But never worry, the IDE will be usually smart enough to do the import for you:
//activity_login is our layout xml import kotlinx.android.synthetic.main.activity_login.*
Henceforth, we can access the views after setContentView is called. Android Studio 3.0+ activity templates now include nested layouts, by using the include tag. It’s important to know that we’ll need to add a synthetic import for any XMLs
we use:
import kotlinx.android.synthetic.main.activity_login.* import kotlinx.android.synthetic.main.content_main.*
Android Extensions for Views
The previous use is not flexible, because there are several other parts of our code where we could need to access the views inside an XML. Take for instance, a custom view or an adapter for a list of items. For these cases, there is an alternative which will bind the views of the XML to another view. The only difference is the required import:
import kotlinx.android.synthetic.main.view_item.view.*
If we were in an adapter, for instance, we could now access the properties of the view inside the ViewHolder just doing this:
itemView.textView.text = "I love programming!"
Take into consideration that, as in extension functions, the views here won’t be cached by the plugin. So if you have a very complex layout, it might be worth implementing this yourself inside the ViewHolder. Otherwise, it could affect the RecyclerView performance in the long run.
Let’s look at a basic example of a RecyclerView that displays a list of TODO-list
activity_todolist.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/forecastList" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout>
TodoListActiviy.java
import kotlinx.android.synthetic.main.activity_main.* override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_todolist) forecastList.layoutManager = LinearLayoutManager(this) ... }
From the code snippets above, the simplification was minimal because this layout is pretty too simple. But the ToDoListAdapter can also benefit from the use of this plugin. Here, we can use the mechanism to bind the properties into a view, which will help us remove all the find code inside the ViewHolder.
To use this plugin in your Adapter add this:
import kotlinx.android.synthetic.main.item_todolist.view.*
Note: item_todolist in the import is your custom view
And now we can find the views from itemView property inside the ViewHolder. In fact you can use those properties over any other views, but it will obviously crash if the view doesn’t contain the requested sub-views. We don’t need to declare properties for the views anymore, we now can just use
them
class ViewHolder(view: View, val itemClick: (ToDo) -> Unit) : RecyclerView.ViewHolder(view) { fun bindToDo(todo: ToDo) { with(todo) { itemView.title.text = title itemView.description.text = description itemView.dateCreated.text = "$datecreated" itemView.expiresOn.text = "$expiresOn" itemView.setOnItemClickListener { itemClick(this) } } } }
In conclusion, our layout is pretty simple and it won’t probably affect performance. But don’t forget I emphasized this approach is not caching the views, so every bind will be doing findViewById under the hood for all its views.
Would you like to know why I love Kotlin Android Extensions plugin?
It helps me reduce some more boilerplate and minimises the code required to access my views.
No Comment! Be the first one.