Created
April 11, 2023 18:22
-
-
Save AAverin/de25adbddb2c121a12128d59e14a675e to your computer and use it in GitHub Desktop.
Component-based adapter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CmpntViewHolder<T>(val cmpnt: Cmpnt<T>, view: View) : RecyclerView.ViewHolder(view) | |
abstract class Cmpnt<T>(@field:LayoutRes private val cmpntLayoutId: Int) { | |
open fun setData(data: T) {} | |
protected open fun onViewCreated(view: View) {} | |
fun createView(inflater: LayoutInflater, parent: ViewGroup?): View { | |
val view = inflater.inflate(cmpntLayoutId, parent, false) | |
onViewCreated(view) | |
return view | |
} | |
fun onVisible() {} | |
fun onHidden() {} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CmpntrRecyclerAdapter(private val layoutInflater: LayoutInflater) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | |
private var items: List<Any> = listOf() | |
fun setItems(newItems: List<Any>): Boolean { | |
val oldItems = items | |
items = newItems as MutableList<Any> | |
DiffUtil.calculateDiff(SimpleDiffUtilCallback(newItems, oldItems)).dispatchUpdatesTo(this) | |
return oldItems != newItems | |
} | |
//public to be accessible by `register` inline function | |
var cmpntProviders = LinkedHashMap<Class<out Any>, () -> Cmpnt<*>>() | |
inline fun <reified T : Any> register(noinline cmpntProvider: () -> Cmpnt<T>) { | |
cmpntProviders[T::class.java] = cmpntProvider | |
} | |
override fun getItemViewType(position: Int) = cmpntProviders.keys.indexOf(items[position].javaClass) | |
override fun getItemId(position: Int): Long = position.toLong() | |
override fun getItemCount() = items.size | |
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | |
val cmpnt = cmpntProviders.values.elementAt(viewType)() | |
return CmpntViewHolder(cmpnt, cmpnt.createView(layoutInflater, parent)) | |
} | |
@Suppress("UNCHECKED_CAST") | |
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | |
(holder as CmpntViewHolder<Any>).cmpnt.setData(items[position]) | |
} | |
@Suppress("UNCHECKED_CAST") | |
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) { | |
super.onViewAttachedToWindow(holder) | |
(holder as CmpntViewHolder<Any>).cmpnt.onVisible() | |
} | |
@Suppress("UNCHECKED_CAST") | |
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { | |
super.onViewDetachedFromWindow(holder) | |
(holder as CmpntViewHolder<Any>).cmpnt.onHidden() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//as an example how to use Cmpnt | |
//first setup an adapter somewhere and register components on it | |
class CmpntrLib @Inject constructor( | |
private val gleamCmpntProvider: Provider<GleamCmpnt>, | |
) { | |
fun setup(recycler: RecyclerView, adapter: CmpntrRecyclerAdapter) { | |
recycler.adapter = adapter | |
adapter.apply { | |
register { gleamCmpntProvider.get() } | |
} | |
} | |
} | |
class GleamCmpnt @Inject constructor( | |
private val timeHelper: TimeHelper, | |
private val analytics: FirebaseAnalytics | |
) : Cmpnt<GleamEntry>(R.layout.cmpnt_gleam_long) { | |
lateinit var binding: CmpntGleamLongBinding | |
override fun setData(data: GleamEntry) { | |
super.setData(data) | |
binding.data = data | |
binding.executePendingBindings() | |
} | |
override fun onViewCreated(view: View) { | |
super.onViewCreated(view) | |
binding = DataBindingUtil.bind(view)!! | |
binding.cmpnt = this | |
binding.timeHelper = timeHelper | |
} | |
fun click(view: View) { | |
//... | |
} | |
fun clickSource(view: View) { | |
// ... | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SimpleDiffUtilCallback<T>( | |
protected val newItems: List<T>, | |
protected val oldItems: List<T> | |
) : DiffUtil.Callback() { | |
override fun getOldListSize() = oldItems.size | |
override fun getNewListSize() = newItems.size | |
override fun areItemsTheSame(oldPosition: Int, newPosition: Int) = newItems[newPosition] == oldItems[oldPosition] | |
override fun areContentsTheSame(oldPosition: Int, newPosition: Int) = newItems[newPosition] == oldItems[oldPosition] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment