I. Requirements and specifications

1, requirements,

RecyclerView is a commonly used list control. When used directly, a lot of code is usually written in Adapter. When item contains too many view types, Adapter will be bloated, so it is necessary to define and write views of each type separately.

2, specification

Five modules are defined: Adapter, viewHolder, viewHolderFactory, itemView and Model

  • Adapter: and recyclerView. adapter adapter, used to integrate fill data
  • ViewHolder: andRecyclerView.ViewHolderA view holder for view reuse
  • ViewHolderFactory: Create a viewHolder and implement the multi-type view Settings
  • ItemView: Item view code
  • Model: Define public models for ease of use

Second, code writing

RecyclerViewAdapter

abstract class RecyclerViewAdapter<M: RecyclerViewModel>(private var context: Context) :
    RecyclerView.Adapter<RecyclerViewHolder<M, out ViewDataBinding, out ItemRecyclerView<M, out ViewDataBinding>>>() {

    private val dataList: MutableList<M> by lazy {
        ArrayList<M>()
    }

    fun addAllDataList(dataList: List<M>) {
        this.dataList.addAll(dataList)
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return dataList.size
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerViewHolder<M, out ViewDataBinding, out ItemRecyclerView<M, out ViewDataBinding>> {
        return createViewHolderFactory().createViewHolder(context, parent, viewType)
    }

    protected abstract fun createViewHolderFactory(): ViewHolderFactory<M>

    override fun onBindViewHolder(
        holder: RecyclerViewHolder<M, out ViewDataBinding, out ItemRecyclerView<M, out ViewDataBinding>>,
        position: Int
    ) {
        holder.itemRecyclerView.dataBinding(dataList[position], position)
    }

}

RecyclerViewHolder

class RecyclerViewHolder<M: RecyclerViewModel, VDB: ViewDataBinding, V: ItemRecyclerView<M, VDB>>(var itemRecyclerView: V)
    : RecyclerView.ViewHolder(itemRecyclerView.rootView)

ViewHolderFactory

abstract class ViewHolderFactory<M: RecyclerViewModel> {
    abstract fun createViewHolder(context: Context, parent: ViewGroup, viewType: Int): 
            RecyclerViewHolder<M, out ViewDataBinding, out ItemRecyclerView<M, out ViewDataBinding>>
}

ItemRecyclerView

abstract class ItemRecyclerView<M: RecyclerViewModel, VDB: ViewDataBinding>(context: Context, parent: ViewGroup) {

    val binding: VDB by lazy {
        DataBindingUtil.inflate(LayoutInflater.from(context), getItemLayoutId(), parent, false) as VDB
    }

    val viewHolder: RecyclerViewHolder<M, VDB, out ItemRecyclerView<M, VDB>> by lazy {
        RecyclerViewHolder(this)
    }

    val rootView: View by lazy {
        binding.root
    }

    abstract fun dataBinding(m: M, position: Int)

    abstract fun getItemLayoutId(): Int
}

RecyclerViewModel

abstract class RecyclerViewModel
Copy the code

Three, use,

DemoViewHolderFactory class DemoViewHolderFactory: ViewHolderFactory<DemoModel>() { override fun createViewHolder( context: Context, parent: ViewGroup, viewType: Int ): RecyclerViewHolder<DemoModel, *, *> { return DemoItemView(context, parent).viewHolder } } DemoItemView class DemoItemView(context: Context, parent: ViewGroup): ItemRecyclerView<DemoModel, ItemDemoBinding>(context, parent) { override fun dataBinding(m: DemoModel, position: Int) { binding.demo = m } override fun getItemLayoutId(): Int { return R.layout.item_demo } } DemoModel class DemoModel: RecyclerViewModel() { var title: String? = null var content: String? = null } DemoAdapter class DemoAdapter(context: Context): RecyclerViewAdapter<DemoModel>(context) { override fun createViewHolderFactory(): ViewHolderFactory<DemoModel> { return DemoViewHolderFactory() } } MainActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main) binding.demoListView.layoutManager = LinearLayoutManager(this) val adapter = DemoAdapter(this) binding.demoListView.adapter = adapter val dataList = ArrayList<DemoModel>() for (i in 0.. 20) { val data = DemoModel() data.title = "title $i" data.content = "content $i" dataList.add(data) } adapter.addAllDataList(dataList) } } activity_main <? The XML version = "1.0" encoding = "utf-8"? > <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/demo_list_View" android:layout_width="match_parent" android:layout_height="match_parent" /> < / androidx constraintlayout. Widget. Constraintlayout > < / layout > item_demo <? XML version = "1.0" encoding = "utf-8"? > < layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="demo" type="com.ww7h.bigobj.DemoModel" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/title" android:text="@{demo.title}" app:layout_constraintTop_toTopOf="parent" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView android:text="@{demo.content}" app:layout_constraintTop_toBottomOf="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>Copy the code