It is common to create lists with recyclerview in almost every project, which take us to create Adapter and ViewHolder for every list. In some cases we go through this process too many times, when there are many lists in our app. In this article we use Kotlin features to create simple lists in easier and faster way . Let’s begin with introducing the results of what we will get. recyclerView. (users, R.layout. , nameText. = . surNameText. = . ) setUp item_layout { text it name text it surname} Of course for this magic we also need kotlin android extensions. Step 1 Let’s create an AbstractAdapter in a generic way We need to pass to the constructor the actual list of items and layout res id AbstractAdapter<ITEM> ( : List<ITEM>, : Int): RecyclerView.Adapter<AbstractAdapter.Holder>() { abstract class constructor protected var itemList private val layoutResId **class** Holder(itemView: View) : RecyclerView.ViewHolder(itemView) } Also, we need to create our view holder extending from base ViewHolder and implement our adapter’s onBindViewHolder and onCreateViewHolder as we always do when creating recyclerview. getItemCount() = .**size override fun itemList override fun** onCreateViewHolder(parent: ViewGroup,viewType: Int): Holder { view = parent Holder(view)} val inflate layoutResIdreturn onBindViewHolder(holder: Holder, position: Int) { item = [position]holder. . (item)} override fun val itemList itemView bind View.bind(item: ITEM) {} protected open fun Holder(itemView: View) : RecyclerView.ViewHolder(itemView) class And we also need to create adapter extending from our abstract adapter, don’t panic, it’s shorter, let’s name it Kadapter. Kadapter<ITEM>(items: List<ITEM>,layoutResId: Int, : View.(ITEM) -> Unit): AbstractAdapter<ITEM>(items, layoutResId) { class private val bindHolder **override fun** onBindViewHolder(holder: Holder, position: Int) { holder.**itemView**.**bindHolder**(**itemList**\[position\]) } } Step 2 Let’s see how our advanced Adapter is going to be used: adapter = Kadapter(users, R.layout. ) nameText. = . surNameText. = .**surname}**recyclerView. = adapterrecyclerView. = LinearLayoutManager( ) val item_layout { text it name text it adapter layoutManager this We can just use it in this way, or go deeper. For that let’s move forward and add more stuff. Superhero landing! He’s going to do a superhero landing! Let’s create an extension to recycler view. <ITEM> RecyclerView.setUp(items: List<ITEM>,layoutResId: Int,bindHolder: View.(ITEM) -> Unit,manager: RecyclerView.LayoutManager = LinearLayoutManager( . )): Kadapter<ITEM> { fun this context **return** Kadapter(items, layoutResId, **{** bindHolder(**it**) **}**)._apply_ **{** _layoutManager_ \= manager _adapter_ \= **this } **} It will encapsulate adapter and layout manager, also we can change layout manager default implementation. Step 3 Everything was fine so far, but if we try to click the item in the list, nothing will happen. We need to take care about that. Let’s implement onClickListener. For that we need to add click logic in our abstract adapter. Our onCreateViewHolder becomes this. onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder { view = parent viewHolder = Holder(view) itemView = viewHolder. itemView.setOnClickListener adapterPosition = viewHolder. (adapterPosition != RecyclerView. ) { (itemView, adapterPosition)} viewHolder} override fun val inflate layoutResIdval val itemView {val adapterPosition if NO_POSITION onItemClick }return onItemClick(itemView: View, position: Int) {} protected open fun We also need to add onClick logic to our adapter implementation and extensions we created before. The final code of kadapter looks like this: Kadapter<ITEM>(items: List<ITEM>,layoutResId: Int, : View.(ITEM) -> Unit): AbstractAdapter<ITEM>(items, layoutResId) { class private val bindHolder **private var itemClick**: ITEM.() -> Unit = **{} constructor**(items: List<ITEM>, layoutResId: Int, bindHolder: View.(ITEM) -> Unit, itemClick: ITEM.() -> Unit = **{}**) : **this**(items, layoutResId, bindHolder) { **this**.**itemClick** \= itemClick } **override fun** onBindViewHolder(holder: Holder, position: Int) { holder.**itemView**.**bindHolder**(**itemList**\[position\]) } **override fun** onItemClick(itemView: View, position: Int) { **itemList**\[position\].**itemClick**() } } And final code for extension <ITEM> RecyclerView.setUp(items: List<ITEM>,layoutResId: Int,bindHolder: View.(ITEM) -> Unit,itemClick: ITEM.() -> Unit = ,manager: RecyclerView.LayoutManager = LinearLayoutManager( . )): Kadapter<ITEM> { Kadapter(items, layoutResId, bindHolder( ) , itemClick() ). = manager = **this}**} fun {} this context return { it } { } apply { layoutManager adapter Now let’s see what we achieved. We can create adapter without click listener and with click listener. recyclerView. (users, R.layout. , nameText. = . surNameText. = . ) setUp item_layout { text it name text it surname} And with click recyclerView. (users, R.layout. , nameText. = . surNameText. = . , toast( ) ) setUp item_layout { text it name text it surname} { "Clicked $name" } As a bonus we can add base methods to our abstract adapter, such as add, remove, update of course using diffUtils. The bottom line of this article is demonstrating some of the powerful features of + , which makes the code more flexible. Now you can go further if interested. Kotlin Android Thanks for reading this article. You can find full code there . Let’s become friends on Twitter , Github and Facebook . If you enjoyed the writings then please use the clap below to recommend this article so that others can see it. We will also love to hear your comments and suggestions :) Thanks.
Share Your Thoughts