Skip to content

Commit 8958226

Browse files
committed
BaseRecyclerView added
1 parent 7d1bdc3 commit 8958226

File tree

12 files changed

+221
-0
lines changed

12 files changed

+221
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package ru.sir.presentation.base.recycler_view
2+
3+
import androidx.databinding.ViewDataBinding
4+
import androidx.recyclerview.widget.RecyclerView
5+
import ru.sir.presentation.base.BaseViewModel
6+
7+
class BaseViewHolder<M, I : RecyclerViewBaseItem<M, out BaseViewModel>>(
8+
private val binding: ViewDataBinding,
9+
private val viewModel: I
10+
) : RecyclerView.ViewHolder(binding.root) {
11+
12+
fun bindData(item: M) {
13+
viewModel.bindData(item)
14+
}
15+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package ru.sir.presentation.base.recycler_view
2+
3+
import android.view.ViewGroup
4+
import androidx.annotation.LayoutRes
5+
import androidx.recyclerview.widget.RecyclerView
6+
import ru.sir.presentation.base.BaseViewModel
7+
import java.lang.IllegalStateException
8+
9+
class RecyclerViewAdapter(private val producers: MutableMap<Int, ViewHolderProducer<*, *, *>>) : RecyclerView.Adapter<BaseViewHolder>() {
10+
11+
private var data = mutableListOf<String>()
12+
13+
class Builder<VM : BaseViewModel>(private val viewModel: VM) {
14+
private val producers = mutableMapOf<Int, ViewHolderProducer<*, *, *>>()
15+
16+
fun <M, I : RecyclerViewBaseItem<M, VM>> addProducer(type: Int, @LayoutRes layoutId: Int, modelClassType: Class<M>, itemViewModelClassType: Class<I>): Builder<VM> {
17+
val producer: ViewHolderProducer<M, I, VM> = ViewHolderProducer(type, layoutId, modelClassType, itemViewModelClassType)
18+
return addProducer(producer)
19+
}
20+
21+
fun <M, I : RecyclerViewBaseItem<M, VM>> addProducer(producer: ViewHolderProducer<M, I, VM>): Builder<VM> {
22+
producer.setParentViewModel(viewModel)
23+
producers[producer.getViewType()] = producer
24+
return this
25+
}
26+
27+
fun build() = RecyclerViewAdapter(producers)
28+
}
29+
30+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<*, *> {
31+
return producers[viewType]?.produce(parent)
32+
?: throw IllegalStateException("View Holder Producer not found!")
33+
}
34+
35+
override fun onBindViewHolder(holder: BaseViewHolder<*, *>, position: Int) {
36+
holder.bindData(data[position])
37+
}
38+
39+
override fun getItemCount(): Int = data.size
40+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package ru.sir.presentation.base.recycler_view
2+
3+
import ru.sir.presentation.base.BaseViewModel
4+
5+
abstract class RecyclerViewBaseItem<M, VM : BaseViewModel> {
6+
protected lateinit var parent: VM
7+
8+
fun init(parent: VM) {
9+
this.parent = parent
10+
}
11+
12+
abstract fun bindData(data: M)
13+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package ru.sir.presentation.base.recycler_view
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.annotation.LayoutRes
6+
import androidx.databinding.DataBindingUtil
7+
import androidx.databinding.ViewDataBinding
8+
import ru.sir.presentation.base.BaseViewModel
9+
10+
class ViewHolderProducer<M, I : RecyclerViewBaseItem<M, VM>, VM : BaseViewModel>(val type: Int, @LayoutRes val layoutId: Int, val modelClassType: Class<M>, private val itemViewModelClassType: Class<I>) {
11+
private lateinit var parentViewModel: VM
12+
13+
fun setParentViewModel(viewModel: VM) {
14+
parentViewModel = viewModel
15+
}
16+
17+
fun getViewType() = type
18+
19+
fun produce(parent: ViewGroup): BaseViewHolder<M, I> {
20+
val binding = DataBindingUtil.inflate<ViewDataBinding>(
21+
LayoutInflater.from(parent.context),
22+
layoutId,
23+
parent,
24+
false
25+
)
26+
27+
return BaseViewHolder(binding, instantiateViewModel())
28+
}
29+
30+
private fun instantiateViewModel(): I {
31+
val viewModelClass = itemViewModelClassType.newInstance()
32+
viewModelClass.init(parentViewModel)
33+
return viewModelClass
34+
}
35+
}

features/example1/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,6 @@ dependencies {
5555
implementation constraintLayout
5656
implementation dagger
5757
kapt daggerCompiler
58+
59+
implementation recyclerView
5860
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package ru.bis.example1.ui.adapters
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.databinding.DataBindingUtil
6+
import androidx.recyclerview.widget.RecyclerView
7+
import ru.bis.example1.R
8+
import ru.bis.example1.databinding.ItemExample1Binding
9+
10+
class Example1Adapter(private val items: MutableList<String>): RecyclerView.Adapter<Example1ViewHolder>() {
11+
12+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Example1ViewHolder {
13+
val binding = DataBindingUtil.inflate<ItemExample1Binding>(
14+
LayoutInflater.from(parent.context),
15+
R.layout.item_example1,
16+
parent,
17+
false
18+
)
19+
20+
return Example1ViewHolder(binding)
21+
}
22+
23+
override fun onBindViewHolder(holder: Example1ViewHolder, position: Int) {
24+
holder.bind(items[position])
25+
}
26+
27+
override fun getItemCount(): Int = items.size
28+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package ru.bis.example1.ui.adapters
2+
3+
import androidx.recyclerview.widget.RecyclerView
4+
import ru.bis.example1.databinding.ItemExample1Binding
5+
import ru.bis.example1.view_models.ItemViewModel
6+
7+
class Example1ViewHolder(private val binding: ItemExample1Binding) : RecyclerView.ViewHolder(binding.root) {
8+
init {
9+
binding.viewModel = ItemViewModel()
10+
}
11+
12+
fun bind(item: String) {
13+
binding.viewModel?.title?.set(item)
14+
}
15+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package ru.bis.example1.view_models
2+
3+
import androidx.databinding.BindingAdapter
4+
import androidx.recyclerview.widget.RecyclerView
5+
import ru.sir.presentation.base.recycler_view.RecyclerViewAdapter
6+
7+
@BindingAdapter(value = ["recyclerAdapter"], requireAll = false)
8+
fun setRecyclerAdapter(view: RecyclerView, adapter: RecyclerViewAdapter) {
9+
view.adapter = adapter
10+
}

features/example1/src/main/java/ru/bis/example1/view_models/Example1ViewModel.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ package ru.bis.example1.view_models
22

33
import android.app.Application
44
import androidx.databinding.ObservableField
5+
import androidx.recyclerview.widget.RecyclerView
56
import ru.bis.example1.R
7+
import ru.bis.example1.ui.adapters.Example1Adapter
68
import ru.bis.example1_api.interactor.GetDataFromCache
79
import ru.sir.core.None
810
import ru.sir.presentation.base.BaseViewModel
11+
import ru.sir.presentation.base.recycler_view.RecyclerViewAdapter
912
import javax.inject.Inject
1013

1114
class Example1ViewModel @Inject constructor(
@@ -14,9 +17,15 @@ class Example1ViewModel @Inject constructor(
1417
) : BaseViewModel(application) {
1518

1619
val result = ObservableField<String>()
20+
val items = mutableListOf<String>()
1721

1822
override fun init() {
1923
getDataFromCache(None()) { it.either(::onLoadDataFromCacheFailed, ::onLoadDataFromCacheSuccess) }
24+
25+
items.add("String 1")
26+
items.add("String 2")
27+
items.add("String 3")
28+
items.add("String 4")
2029
}
2130

2231
private fun onLoadDataFromCacheSuccess(data: String) {
@@ -26,4 +35,8 @@ class Example1ViewModel @Inject constructor(
2635
private fun onLoadDataFromCacheFailed(failed: None) {
2736
result.set(context.getString(R.string.load_data_failed))
2837
}
38+
39+
fun recyclerViewAdapter() = RecyclerViewAdapter.Builder(this)
40+
.addProducer(1, R.layout.item_example1, String::class.java, ItemViewModel::class.java)
41+
.build()
2942
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package ru.bis.example1.view_models
2+
3+
import androidx.databinding.ObservableField
4+
import ru.sir.presentation.base.recycler_view.RecyclerViewBaseItem
5+
6+
class ItemViewModel : RecyclerViewBaseItem<String, Example1ViewModel>() {
7+
val title = ObservableField("")
8+
9+
override fun bindData(data: String) {
10+
title.set(data)
11+
}
12+
}

0 commit comments

Comments
 (0)