· 4 min read

Writing a RecyclerView Adapter in Kotlin (KAD 16)

An interesting way to see how Kotlin simplifies your life is by creating a RecyclerView Adapter.

You’ll see that the code can be organized in such a way that its reading is easier and it avoids redundant code.

RecyclerView Adapter in Kotlin

We’ll create an Adapter that will set a title and an image into a cell.

It’ll be a very simple adapter in which we won’t allow the modification of the items. If we want new data, we will create a new adapter and set it to the RecyclerView.

If all this passionate you as to me, I encourage you to sign up for my free training where I will tell you everything you need to learn about how to create your Android Apps in Kotlin from scratch.

Free Training

The model

We’ll use a very simple model too, which only needs an identifier, the title and the url of the image.

We’ll use a data class, which if you remember we saw a few articles ago:

data class Item(val id: Long, val title: String, val url: String)

With this we already have a class with its constructor, its immutable properties, and other useful functions like equals or hashCode implemented.

The Adapter

The Adapter’s structure would be the following, self-generating the necessary methods:

class MyAdapter : RecyclerView.Adapter() {
     
    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
    }

    override fun getItemCount(): Int {
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}

You’ll see that I’ve created a ViewHolder class, which extends from the original.

This is because the Adapter needs an implementation of the original abstract class.

Also, there are some elements marked as nullable. This is because if the library isn’t properly annotated with the annotations @Nullable and @NonNull, Kotlin has no way of knowing if nulls are allowed, and it lets us decide.

If we self-generate the methods, by default it’ll take for granted that the values are nullable.

But studying the support library a bit, we know that those values aren’t null, so we can remove it:

class MyAdapter : RecyclerView.Adapter() {
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    }

    override fun getItemCount(): Int {
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}

The constructor

The adapter needs to receive the items and a listener by parameter. The result is something like this:

class MyAdapter(val items: List<Item>, val listener: (Item) -> Unit)

The implementation of the methods is very easy. I’m using an extension function that I’d created in a previous article to inflate the view:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.view_item))

override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position], listener)

override fun getItemCount() = items.size

There are three methods can be implemented with the contracted form, obtaining the previous result. In three lines we have all the adapter implemented.

Now go for the ViewHolder implementation.

The ViewHolder

The ViewHolder will assign the values from the model to their corresponding views:

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(item: Item, listener: (Item) -> Unit) = with(itemView) {
        itemTitle.text = item.title
        itemImage.loadUrl(item.url)
        setOnClickListener { listener(item) }
    }
}

Everything we have here has already been seen in other articles: the with function, the loadUrl extension function for ImageView, the access to Views using Kotlin Android Extensions and the mapping of the click listener.

As mentioned by Nabil in the comments, this way to use Kotlin Android Extensions in Views has some hidden costs, and is not always optimal. Take a look at the Kotlin Android Extensions article in this blog, where I show a new way to use cache on ViewHolders, and also this other article which talks about this hidden costs I’m mentioning. In any case, my recommendation is to test before optimizing.

Adapter assignment

There’s only one thing left: assign the adapter to the view

recycler.layoutManager = GridLayoutManager(this, 2)
recycler.adapter = MyAdapter(items) {
    toast("${it.title} Clicked")
}

The final function is listener, which receives an item. The code will simply print the title of the item you click on.

Conclusion

As simple as that is to implement a RecyclerView Adapter in Kotlin.

Using a few of the tools we have learned so far, we’ve simplified the code to the minimum.

Cheer up and come to my free training. I will tell you everything you need to learn about how to create your own Android Apps in Kotlin from scratch. Discover everything about the language of the future.

    Share:
    Back to Blog