Middleman

A Better way to handle items in the Simple list and Paged list in RecyclerView.

https://www.entefy.com/img/219561d96ac75a93b702bee818235f58.jpg

what is the problem?
in almost all of the Android applications, recyclerview is a mandatory part.

and the adapter is the key point of implementing a recyclerview.

this is the way most people handle recyclerViewAdapters:

class SampleRecyclerView: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
ViewType1 -> {
createViewHolder1()
}
ViewType2 -> {
createViewHolder2()
}
else -> {
            }
}
}
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder.bind(items)
}
    class ViewHolder1(val itemView1: View) : RecyclerView.ViewHolder(itemView1) {
    }
    class ViewHolder2(val itemView1: View) : RecyclerView.ViewHolder(itemView1) {
    }

....
}

so what’s wrong with this implementation?
1- you have to modify your adapter every time you add a new item to your recyclerview. 
2- you have to create a different adapter for each page of your app or after a while you find your self in a big mess. 
3- you cannot interact with your fragment or activity from your items directly. 4- if after a while someone new came to the development team they have the problem in finding items in each page of the application.

Solution

Using the Middleman
How to Use Middleman?
create an instance of GeneralViewAdapter and set it to recyclerView

recyclerView.apply {
       adapter = GeneralViewAdapter(this@SampleListFragment)
// or for support paging in your list
adapter = GeneralPagingViewAdapter(this@SampleListFragment)

layoutManager = LinearLayoutManager(activity)
}

implement BaseModel in every item model.
implement defaultResLayout or defaultViewClass method. 
you can declare a res layout or a class of your customView item.

@Parcelize
class ItemModel(val id:String,val name:String):BaseModel{
override fun defaultResLayout(position: Int): Int? {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
    override fun defaultViewClass(position: Int): Class<*>? {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}

create a customView for each item in your recycler view that implements Binder interface and if need to interact with activity or fragment implement the corresponding interactor.

open class ItemView @JvmOverloads constructor(
context: Context,
attributes: AttributeSet? = null,
defStyleAttributes: Int = 0
) : LinearLayoutCompat(context, attributes, defStyleAttributes)
, Binder<ItemModel>
, RequireInteractor<SomeIntractor> {
    private lateinit var someIntractor: SomeIntractor
    override fun setInteractor(intractor: SomeIntractor) {
this.someIntractor = intractor
}
    override fun bind(item: ItemModel?) {
....
}
}

and that’s it.

so
1- you don’t need to modify adapter every time you create a new Item in the list. 
2- you don’t need to create a different adapter for different pages. 
3- you can easily interact with your fragment and activity from your items. 
4- and if a new member came in your development team because every item is custom view they can easily find the items in a big project with help of layout inspector in the android studio.

whats an intractor?

Interactors are a bridge between items in the list and your fragment or your activity.

technically is just an interface that you extended from “BaseIntractor” and implement your functions and methods.

what "defaultViewClass" and "defaultResLayout" methods do?

you implement this methods to provide item view for the adapter .

in defaultViewClass you return a class of the customView that you created for the view item and GeneralViewAdapter use reflection to create a new instance of it.

or you can return res layout in defaultResLayout to create the item with view inflation.

https://github.com/mohamadk/MiddleMan