From 65b79b5c4ad938cc14cbdf75f8dc84ddc3e8f6c8 Mon Sep 17 00:00:00 2001 From: Rakhimulin Damir Date: Tue, 16 Feb 2021 11:17:39 +0300 Subject: [PATCH 1/2] ViewBinder refactoring. Added onDetachedFromWindow & onAttachedToWindow to HolderBinder --- .../rerekt/rekukler/MultibindingsAdapter.kt | 16 ++++- .../java/com/rerekt/rekukler/ViewBinder.kt | 69 +++++++++++++++---- .../java/com/rerekt/sample/ui/ListFragment.kt | 1 - .../rerekt/sample/ui/global/list/articles.kt | 10 +++ 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/rekukler/src/main/java/com/rerekt/rekukler/MultibindingsAdapter.kt b/rekukler/src/main/java/com/rerekt/rekukler/MultibindingsAdapter.kt index 337ff40..ca0ed12 100644 --- a/rekukler/src/main/java/com/rerekt/rekukler/MultibindingsAdapter.kt +++ b/rekukler/src/main/java/com/rerekt/rekukler/MultibindingsAdapter.kt @@ -39,7 +39,11 @@ open class MultiBindingAdapter( ) override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) = - getBinder(position).bindViewHolder(viewHolder, items[position], position) + getBinder(position).bindViewHolder( + viewHolder = viewHolder as RekuklerViewHolder<*, *>, + position = position, + item = items[position] + ) private fun getBinder(position: Int): ViewBinder<*, *> { val item = items[position] @@ -49,6 +53,16 @@ open class MultiBindingAdapter( ) } + override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { + (holder as RekuklerViewHolder<*, *>).onDetachedFromWindow() + super.onViewDetachedFromWindow(holder) + } + + override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) { + (holder as RekuklerViewHolder<*, *>).onAttachedToWindow() + super.onViewAttachedToWindow(holder) + } + override fun getItemCount() = items.size /** diff --git a/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt b/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt index 213f9db..e73dc20 100644 --- a/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt +++ b/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt @@ -16,46 +16,81 @@ class ViewBinder ( val isForItem: (item: Any) -> Boolean, val areItemsSame: (Type, Type) -> Boolean, val areContentsSame: (Type, Type) -> Boolean, - private val holderBinder: Holder.(Type) -> Unit + private val holderBinder: HolderBinder.(Type) -> Unit ) { - fun createViewHolder(parent: ViewGroup): RecyclerView.ViewHolder { + fun createViewHolder(parent: ViewGroup): RekuklerViewHolder { val itemView = LayoutInflater.from(parent.context).inflate(layoutResId, parent, false) - return object : RecyclerView.ViewHolder(itemView) {} + return RekuklerViewHolder( + itemView = itemView, + binder = binder, + holderBinder = holderBinder + ) } @Suppress("UNCHECKED_CAST") - fun bindViewHolder(viewHolder: RecyclerView.ViewHolder, item: Any, position: Int) { - Holder(viewHolder) - .apply { - holderBinder(item as Type) - itemPosition = position - bindingBlock.invoke(binder.invoke(viewHolder.itemView), item) - } + fun bindViewHolder(viewHolder: RekuklerViewHolder<*, *>, item: Any, position: Int) { + viewHolder.bind(item, position) } } +@Suppress("UNCHECKED_CAST") +open class RekuklerViewHolder( + itemView: View, + val binder: (View) -> Binding, + private val holderBinder: HolderBinder.(Type) -> Unit +) : RecyclerView.ViewHolder(itemView) { + + internal val holder = HolderBinder(this) + private var binding: Binding? = null + + fun bind(item: Any, position: Int) { + holder.apply { + binding = binder.invoke(viewHolder.itemView) + holderBinder(item as Type) + itemPosition = position + bindingBlock.invoke(binding!!, item) + } + } + + fun onDetachedFromWindow() { + binding?.let { + holder.onDetachedFromWindow.invoke(it) + } + } + + fun onAttachedToWindow() { + binding?.let { + holder.onAttachedToWindow.invoke(it) + } + } + +} + inline fun viewBinder( @LayoutRes layoutResId: Int, noinline isForItem: (item: Any) -> Boolean = { it is Type }, noinline areItemsSame: (Type, Type) -> Boolean = { old, new -> old == new }, noinline areContentsSame: (Type, Type) -> Boolean = { old, new -> old == new }, noinline binder: (View) -> Binder, - noinline holder: Holder.(Type) -> Unit = {} + noinline holderBinder: HolderBinder.(Type) -> Unit = {} ) = ViewBinder( layoutResId = layoutResId, binder = binder, isForItem = isForItem, areItemsSame = areItemsSame, areContentsSame = areContentsSame, - holderBinder = holder + holderBinder = holderBinder ) -class Holder( +class HolderBinder( val viewHolder: RecyclerView.ViewHolder ) { internal var bindingBlock: Binding.(Type) -> Unit = {} + internal var onDetachedFromWindow: Binding.() -> Unit = {} + internal var onAttachedToWindow: Binding.() -> Unit = {} + internal var itemPosition = 0 val itemView: View @@ -68,6 +103,14 @@ class Holder( this.bindingBlock = bindingBlock } + fun onDetachedFromWindow(b: Binding.() -> Unit) { + this.onDetachedFromWindow = b + } + + fun onAttachedToWindow(b: Binding.() -> Unit) { + this.onAttachedToWindow = b + } + fun getString(@StringRes resId: Int): String = itemView.context.getString(resId) fun getString(@StringRes resId: Int, vararg formatArgs: Any): String = itemView.context.getString(resId, *formatArgs) fun getDrawable(@DrawableRes resId: Int): Drawable? = ContextCompat.getDrawable(itemView.context, resId) diff --git a/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt b/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt index 0e8de9a..1cdf697 100644 --- a/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt +++ b/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt @@ -13,7 +13,6 @@ import com.rerekt.rekukler.utils.MarginDividerItemDecoration import com.rerekt.sample.R import com.rerekt.sample.databinding.FragmentMainBinding import com.rerekt.sample.ui.global.dip -import com.rerekt.sample.ui.global.int import com.rerekt.sample.ui.global.list.* class ListFragment: Fragment(R.layout.fragment_main) { diff --git a/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt b/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt index 818c2d0..28b5fee 100644 --- a/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt +++ b/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt @@ -21,6 +21,7 @@ fun articlesBinder( areContentsSame = { old, new -> old == new }, ) { bindView { data -> + println("on item bind") llContainer.setBackgroundColor( ContextCompat.getColor( itemView.context, @@ -35,4 +36,13 @@ fun articlesBinder( tvPosition.text = getString(R.string.position, position) setOnClickListener { onClick.invoke(data) } } + + onDetachedFromWindow { + println("on item detached from window") + } + + onAttachedToWindow { + println("on item attached to window") + } + } From 25cd166fd12e76b3040dbf783381e67e38e44390 Mon Sep 17 00:00:00 2001 From: Rakhimulin Damir Date: Tue, 16 Feb 2021 11:19:36 +0300 Subject: [PATCH 2/2] Removed unnecessary logging --- .../src/main/java/com/rerekt/sample/ui/global/list/articles.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt b/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt index 28b5fee..282b2a0 100644 --- a/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt +++ b/sample/src/main/java/com/rerekt/sample/ui/global/list/articles.kt @@ -21,7 +21,6 @@ fun articlesBinder( areContentsSame = { old, new -> old == new }, ) { bindView { data -> - println("on item bind") llContainer.setBackgroundColor( ContextCompat.getColor( itemView.context,