Skip to content

Commit

Permalink
♻️ Change adapters
Browse files Browse the repository at this point in the history
  • Loading branch information
David Sucharda committed Oct 18, 2021
1 parent 0fed7a0 commit 08d37d4
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ interface BaseBindingAdapter<T : Any> : View.OnClickListener,

viewHolder.binding.root.apply {
setTag(R.id.recycler_view_adapter_item_model, item)
// Must be like this to keep the original value
isClickable = isClickable.also { setOnClickListener(this@BaseBindingAdapter) }
isLongClickable = isLongClickable.also { setOnLongClickListener(this@BaseBindingAdapter) }
}
Expand Down Expand Up @@ -166,12 +167,11 @@ interface BaseBindingAdapter<T : Any> : View.OnClickListener,
* @return true if handled by the [itemLongClickListener] else false
*/
override fun onLongClick(view: View): Boolean {
itemLongClickListener?.let {
return itemLongClickListener?.let {
val item = view.getTag(R.id.recycler_view_adapter_item_model) as T
it.invoke(view, item)
return true
}
return false
true
} ?: false
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
package cz.eman.kaal.presentation.adapter

import android.view.View
import androidx.recyclerview.widget.DiffUtil
import cz.eman.kaal.presentation.adapter.binder.ItemBinder
import cz.eman.kaal.presentation.adapter.binder.VariableBinder

/**
* Wrapper data class for Binding adapter configuration. It is used when binding adapter is being created. Holds only
* common information and all extending information must be handled separately.
*
* @property items displayed in the adapter
* @property itemBinder defines layout for specific item types
* @property variableBinders allows sending custom variables to the layout
* @property itemClickListener enables to handle item click (not sub-view click)
* @property itemLongClickListener enables to handle item long click (not sub-view click)
* @property limit of how many items can be displayed
* @property differ used to compare items
* @author: eMan a.s.
* @since 0.9.0
*/
data class BindingAdapterConfig<T : Any>(
val items: Collection<T>?,
class BindingAdapterConfig<T : Any>(
val itemBinder: ItemBinder<T>,
val variableBinders: Array<VariableBinder<T>>?,
val itemClickListener: ((View, T) -> Unit)?,
val itemLongClickListener: ((View, T) -> Unit)?,
val limit: Int? = null
val limit: Int? = null,
val differ: DiffUtil.ItemCallback<T>? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ fun <T : Any> bindRecyclerView(
requireNotNull(binder) { "ItemBinder must be defined" }

val config = BindingAdapterConfig(
items = items,
itemBinder = binder,
variableBinders = variables,
itemClickListener = clickListener,
itemLongClickListener = longClickListener,
limit = limit
limit = limit,
differ = differ
)
recyclerView.adapter = buildBindingAdapter(config, paging, differ)
recyclerView.adapter = buildBindingAdapter(items, config, paging)
} else {
@Suppress("UNCHECKED_CAST")
adapter as BindingRecyclerViewAdapter<T>
Expand Down Expand Up @@ -83,13 +83,13 @@ fun <T : Any> bindViewPager2(
requireNotNull(binder) { "ItemBinder must be defined" }

val config = BindingAdapterConfig(
items = items,
itemBinder = binder,
variableBinders = variables,
itemClickListener = clickListener,
itemLongClickListener = longClickListener,
differ = differ
)
viewPager.adapter = buildBindingAdapter(config, paging, differ)
viewPager.adapter = buildBindingAdapter(items, config, paging)
} else {
@Suppress("UNCHECKED_CAST")
adapter as BindingRecyclerViewAdapter<T>
Expand All @@ -100,28 +100,25 @@ fun <T : Any> bindViewPager2(
/**
* Builds a binding adapter based on the variables. There are three cases at the moment:
* 1) [BindingRecyclerViewAdapter] is created when paging adapter should not be used.
* 2) [BindingPagingRecyclerViewAdapter] is created when paging adapter is used and [differ] variable is not null, since
* paging adapter requires this variable to be set.
* 3) Identifies that paging adapter should be created but [differ] is missing. It logs the error and created
* [BindingRecyclerViewAdapter] which makes sure data are displayed.
* 2) [BindingPagingRecyclerViewAdapter] is created when paging adapter is used and [BindingAdapterConfig.differ]
* variable is not null, since paging adapter requires this variable to be set.
* 3) Identifies that paging adapter should be created but [BindingAdapterConfig.differ] is missing. It logs the error
* and created [BindingRecyclerViewAdapter] which makes sure data are displayed.
*
* @param config common configuration for any biding adapter
* @param paging true when paging adapter should be created else false
* @param differ [DiffUtil] to be used in the adapter
* @author eMan a.s.
* @see BindingRecyclerViewAdapter.build
* @see BindingPagingRecyclerViewAdapter.build
* @since 0.9.0
*/
private fun <T : Any> buildBindingAdapter(
items: Collection<T>?,
config: BindingAdapterConfig<T>,
paging: Boolean,
differ: DiffUtil.ItemCallback<T>?
paging: Boolean
): RecyclerView.Adapter<*> = when {
!paging -> BindingRecyclerViewAdapter.build(config, differ)
paging && differ != null -> BindingPagingRecyclerViewAdapter.build(config, differ)
!paging -> BindingRecyclerViewAdapter(config, items)
paging && config.differ != null -> BindingPagingRecyclerViewAdapter(config, config.differ)
else -> {
config.logError { "Failed to create BindingPagingRecyclerViewAdapter (no differ supplied)" }
BindingRecyclerViewAdapter.build(config, differ)
BindingRecyclerViewAdapter(config, items)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@ import cz.eman.kaal.presentation.adapter.binder.VariableBinder
*/
@Suppress("UNCHECKED_CAST", "unused")
class BindingPagingRecyclerViewAdapter<T : Any>(
override val itemBinder: ItemBinder<T>,
override val itemClickListener: ((View, T) -> Unit)? = null,
override val itemLongClickListener: ((View, T) -> Unit)? = null,
override val variableBinders: Array<VariableBinder<T>>? = null,
private val limit: Int? = null,
config: BindingAdapterConfig<T>,
differ: DiffUtil.ItemCallback<T>
) : PagingDataAdapter<T, BaseBindingAdapter.ViewHolder>(differ),
BaseBindingAdapter<T> {

override val itemBinder: ItemBinder<T> = config.itemBinder
override val itemClickListener: ((View, T) -> Unit)? = config.itemClickListener
override val itemLongClickListener: ((View, T) -> Unit)? = config.itemLongClickListener
override val variableBinders: Array<VariableBinder<T>>? = config.variableBinders
private val limit: Int? = config.limit

/**
* @see BaseBindingAdapter.getItemInternal
* @see getItem
Expand Down Expand Up @@ -86,24 +88,4 @@ class BindingPagingRecyclerViewAdapter<T : Any>(
* @see Int.coerceAtMost
*/
override fun getItemCount() = super.getItemCount().coerceAtMost(limit ?: Int.MAX_VALUE)

companion object {

/**
* Build function which creates an instance of this adapter with the specific configuration.
*
* @param config used to build this adapter
* @param differ used to build this adapter, allows to make differences between the items
* @return [BindingPagingRecyclerViewAdapter]
*/
fun <T : Any> build(config: BindingAdapterConfig<T>, differ: DiffUtil.ItemCallback<T>) =
BindingPagingRecyclerViewAdapter(
itemBinder = config.itemBinder,
itemClickListener = config.itemClickListener,
itemLongClickListener = config.itemLongClickListener,
variableBinders = config.variableBinders,
limit = config.limit,
differ = differ
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableList
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import cz.eman.kaal.presentation.adapter.binder.ItemBinder
Expand All @@ -28,16 +27,18 @@ import java.lang.ref.WeakReference
*/
@Suppress("UNCHECKED_CAST", "unused")
class BindingRecyclerViewAdapter<T : Any>(
items: Collection<T>? = null,
override val itemBinder: ItemBinder<T>,
override val itemClickListener: ((View, T) -> Unit)? = null,
override val itemLongClickListener: ((View, T) -> Unit)? = null,
override val variableBinders: Array<VariableBinder<T>>? = null,
private val differ: DiffUtil.ItemCallback<T>? = null,
private val limit: Int? = null
config: BindingAdapterConfig<T>,
items: Collection<T>? = null
) : RecyclerView.Adapter<BaseBindingAdapter.ViewHolder>(),
BaseBindingAdapter<T> {

override val itemBinder: ItemBinder<T> = config.itemBinder
override val itemClickListener: ((View, T) -> Unit)? = config.itemClickListener
override val itemLongClickListener: ((View, T) -> Unit)? = config.itemLongClickListener
override val variableBinders: Array<VariableBinder<T>>? = config.variableBinders
private val differ: DiffUtil.ItemCallback<T>? = config.differ
private val limit: Int? = config.limit

/**
* Callback informing that the list has changes. Only as a [WeakReference] to prevent leaks.
*/
Expand Down Expand Up @@ -70,39 +71,39 @@ class BindingRecyclerViewAdapter<T : Any>(
}

/**
* @see PagingDataAdapter.onCreateViewHolder
* @see RecyclerView.Adapter.onCreateViewHolder
* @see BaseBindingAdapter.onCreateViewHolderInternal
*/
override fun onCreateViewHolder(viewGroup: ViewGroup, @LayoutRes layoutId: Int): BaseBindingAdapter.ViewHolder {
return onCreateViewHolderInternal(viewGroup, layoutId)
}

/**
* @see PagingDataAdapter.onBindViewHolder
* @see RecyclerView.Adapter.onBindViewHolder
* @see BaseBindingAdapter.onBindViewHolderInternal
*/
override fun onBindViewHolder(viewHolder: BaseBindingAdapter.ViewHolder, position: Int) {
onBindViewHolderInternal(viewHolder, position)
}

/**
* @see PagingDataAdapter.onViewAttachedToWindow
* @see RecyclerView.Adapter.onViewAttachedToWindow
* @see BaseBindingAdapter.onViewAttachedToWindowInternal
*/
override fun onViewAttachedToWindow(holder: BaseBindingAdapter.ViewHolder) {
onViewAttachedToWindowInternal(holder)
}

/**
* @see PagingDataAdapter.onViewDetachedFromWindow
* @see RecyclerView.Adapter.onViewDetachedFromWindow
* @see BaseBindingAdapter.onViewDetachedFromWindowInternal
*/
override fun onViewDetachedFromWindow(holder: BaseBindingAdapter.ViewHolder) {
onViewDetachedFromWindowInternal(holder)
}

/**
* @see PagingDataAdapter.getItemViewType
* @see RecyclerView.Adapter.getItemViewType
* @see BaseBindingAdapter.getItemViewTypeInternal
*/
@LayoutRes
Expand Down Expand Up @@ -289,25 +290,4 @@ class BindingRecyclerViewAdapter<T : Any>(
adapterReference.get()?.notifyItemRangeRemoved(positionStart, itemCount)
}
}

companion object {

/**
* Build function which creates an instance of this adapter with the specific configuration.
*
* @param config used to build this adapter
* @param differ used to build this adapter, allows to make differences between the items
* @return [BindingRecyclerViewAdapter]
*/
fun <T : Any> build(config: BindingAdapterConfig<T>, differ: DiffUtil.ItemCallback<T>?) =
BindingRecyclerViewAdapter(
items = config.items,
itemBinder = config.itemBinder,
itemClickListener = config.itemClickListener,
itemLongClickListener = config.itemLongClickListener,
variableBinders = config.variableBinders,
limit = config.limit,
differ = differ
)
}
}

0 comments on commit 08d37d4

Please sign in to comment.