diff --git a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BaseBindingAdapter.kt b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BaseBindingAdapter.kt index d8ac5af..a95ec0f 100644 --- a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BaseBindingAdapter.kt +++ b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BaseBindingAdapter.kt @@ -5,6 +5,7 @@ import android.view.View import android.view.ViewGroup import androidx.annotation.IntRange import androidx.annotation.LayoutRes +import androidx.annotation.MainThread import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.lifecycle.Lifecycle @@ -19,8 +20,11 @@ import cz.eman.kaal.presentation.adapter.binder.VariableBinder * Handles basic (common) functionality for Binding adapters. Takes care of view creation, data binding, click listeners * and other common functionality for adapters. * - * This is an interface due to different parents for adapters. It accesses the variable by functions and + * This is an interface due to different parents for adapters. It requires access to multiple variables from the + * extending classes like [itemBinder], [itemClickListener], and others. Prevents code being repeated but it also makes + * the variables public. * + * @property T type of the object handled by this interface * @author eMan a.s. * @author Radek Piekarz * @see [GitHub project](https://github.com/radzio/android-data-binding-recyclerview) @@ -31,17 +35,63 @@ import cz.eman.kaal.presentation.adapter.binder.VariableBinder interface BaseBindingAdapter : View.OnClickListener, View.OnLongClickListener { + /** + * Gets item on a specific position in the adapter. Must be implemented by extending class. + * + * @param position of the item + * @return [T] item or null when not found + */ fun getItemInternal(@IntRange(from = 0) position: Int): T? + /** + * Item binder specifies binding layout for specific item. For more information check [ItemBinder]. + */ val itemBinder: ItemBinder + + /** + * Specifies click action for the whole item layout ([ViewHolder]). Click on any sub-view of the holder must be + * handled separately. Ex: you can send ViewModel using [variableBinders] and bind click directly in layout xml. + */ val itemClickListener: ((View, T) -> Unit)? + + /** + * Same as the [itemClickListener] with the exception that it handles long click instead of click. + */ val itemLongClickListener: ((View, T) -> Unit)? + + /** + * Used to send custom variables to item layout [ViewHolder]. Any variable can be send but most common is ViewModel. + * For more information check [VariableBinder]. + */ val variableBinders: Array>? + /** + * Creates instance of [ViewHolder] with specific binding layout inflated using [layoutId]. + * + * @param viewGroup for the layout inflation + * @param layoutId layout resource identifying which layout should be inflated + * @return inflated [ViewHolder] + * @see ViewHolder + * @see DataBindingUtil.inflate + */ fun onCreateViewHolderInternal(viewGroup: ViewGroup, @LayoutRes layoutId: Int): ViewHolder { return ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(viewGroup.context), layoutId, viewGroup, false)) } + /** + * Binds item data to the [ViewHolder]. Gets the specific item (if possible) and sets it to the view holder binding. + * It also sets any other variables from [variableBinders] binds click listeners (if they are enabled). + * + * Since [ViewHolder] allows variable observing using [Lifecycle] it will set the binding [LifecycleOwner] as a + * [ViewHolder]. It makes sure all variable changes are propagated to the binding. After binding is configured it + * also triggers [ViewDataBinding.executePendingBindings] to make sure all displayed information correspond with the + * item information. + * + * @param viewHolder to have variables and listeners set + * @param position of the item in the list + * @see ViewDataBinding.setVariable + * @see ViewDataBinding.executePendingBindings + */ fun onBindViewHolderInternal(viewHolder: ViewHolder, position: Int) { val item = getItemInternal(position) ?: return viewHolder.binding.apply { @@ -63,45 +113,99 @@ interface BaseBindingAdapter : View.OnClickListener, } } - fun onViewAttachedToWindowInternal(holder: ViewHolder) { - holder.onStart() + /** + * When view is attached to the window the [ViewHolder] starts observing variables. + * + * @param viewHolder to start listening in + * @see ViewHolder.onStart + */ + fun onViewAttachedToWindowInternal(viewHolder: ViewHolder) { + viewHolder.onStart() } - fun onViewDetachedFromWindowInternal(holder: ViewHolder) { - holder.onStop() + /** + * When view is detached from the window the [ViewHolder] stops observing variables. + * + * @param viewHolder to start listening in + * @see ViewHolder.onStop + */ + fun onViewDetachedFromWindowInternal(viewHolder: ViewHolder) { + viewHolder.onStop() } + /** + * Gets item view type by it's [position]. Gets the item using [getItemInternal] and then it gets layout resource + * for it from the [itemBinder]. If it is not found then 0 is returned. + * + * @param position of the item in the list + * @return [Int] with layout resource + * @see getItemInternal + * @see ItemBinder.getLayoutRes + */ @LayoutRes fun getItemViewTypeInternal(position: Int) = getItemInternal(position)?.let { itemBinder.getLayoutRes(it) } ?: 0 - override fun onClick(v: View) { + /** + * Handles click on the item view by getting the item from view tag and invoking [itemClickListener] if it exists. + * + * @param view used to get the item and also being send to the click listener + */ + override fun onClick(view: View) { itemClickListener?.let { - val item = v.getTag(R.id.recycler_view_adapter_item_model) as T - it.invoke(v, item) + val item = view.getTag(R.id.recycler_view_adapter_item_model) as T + it.invoke(view, item) } } - override fun onLongClick(v: View): Boolean { + /** + * Handles long click on the item view by getting the item from view tag and invoking [itemLongClickListener] if it + * exists. + * + * @param view used to get the item and also being send to the click listener + * @return true if handled by the [itemLongClickListener] else false + */ + override fun onLongClick(view: View): Boolean { itemLongClickListener?.let { - val item = v.getTag(R.id.recycler_view_adapter_item_model) as T - it.invoke(v, item) + val item = view.getTag(R.id.recycler_view_adapter_item_model) as T + it.invoke(view, item) return true } return false } + /** + * View holder for the [RecyclerView.Adapter] holding [ViewDataBinding] for the item and also serving as a + * [LifecycleOwner] to listen for any changes in lifecycle events. + * + * @property binding view binding for the holder + * @see RecyclerView.ViewHolder + */ class ViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root), LifecycleOwner { + /** + * @see LifecycleRegistry + */ private val registry: LifecycleRegistry = LifecycleRegistry(this) + /** + * @see LifecycleOwner.getLifecycle + */ override fun getLifecycle(): Lifecycle = registry + /** + * Sets [Lifecycle.Event.ON_START] event to the [registry] to start observing variable changes. + */ + @MainThread fun onStart() { registry.handleLifecycleEvent(Lifecycle.Event.ON_START) } + /** + * Sets [Lifecycle.Event.ON_STOP] event to the [registry] to stop observing variable changes. + */ + @MainThread fun onStop() { registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) } diff --git a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapterConfig.kt b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapterConfig.kt index 046d1de..9b87797 100644 --- a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapterConfig.kt +++ b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapterConfig.kt @@ -5,9 +5,17 @@ import cz.eman.kaal.presentation.adapter.binder.ItemBinder import cz.eman.kaal.presentation.adapter.binder.VariableBinder /** - * Wrapper data class for configuration of Binding adapter. + * 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 * @author: eMan a.s. + * @since 0.9.0 */ data class BindingAdapterConfig( val items: Collection?, diff --git a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapters.kt b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapters.kt index 0072080..6d77ca3 100644 --- a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapters.kt +++ b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingAdapters.kt @@ -12,11 +12,12 @@ import cz.eman.kaal.presentation.adapter.binder.VariableBinder import cz.eman.logger.logError /** - * Binds adapter to [RecyclerView] using [BindingRecyclerViewAdapter]. Parameters are used to create this adapter and - * support item clicks, differences and other options. If the adapter already exists it only changes item list in - * the adapter, which happens with Observable or LiveData items. + * Binds adapter to [RecyclerView] using [BindingRecyclerViewAdapter] or [BindingPagingRecyclerViewAdapter] (based on + * the [paging] variable). Parameters are used to create adapter and support item clicks, differences and other options. + * If the adapter already exists it only changes item list in the adapter, which happens with Observable or LiveData + * items. If the adapter is a pager adapter it does nothing. * - * @author [eMan a.s.](mailto:info@eman.cz) + * @author eMan a.s. * @since 0.8.0 */ @BindingAdapter( @@ -46,7 +47,7 @@ fun bindRecyclerView( itemLongClickListener = longClickListener, limit = limit ) - recyclerView.adapter = buildAdapter(config, paging, differ) + recyclerView.adapter = buildBindingAdapter(config, paging, differ) } else { @Suppress("UNCHECKED_CAST") adapter as BindingRecyclerViewAdapter @@ -55,11 +56,12 @@ fun bindRecyclerView( } /** - * Binds adapter to [ViewPager2] using [BindingRecyclerViewAdapter]. Parameters are used to create this adapter and - * support item clicks, differences and other options. If the adapter already exists it only changes item list in - * the adapter, which happens with Observable or LiveData items. + * Binds adapter to [ViewPager2] using [BindingRecyclerViewAdapter] or [BindingPagingRecyclerViewAdapter] (based on + * the [paging] variable). Parameters are used to create adapter and support item clicks, differences and other options. + * If the adapter already exists it only changes item list in the adapter, which happens with Observable or LiveData + * items. If the adapter is a pager adapter it does nothing. * - * @author [eMan a.s.](mailto:info@eman.cz) + * @author eMan a.s. * @since 0.8.0 */ @BindingAdapter( @@ -87,7 +89,7 @@ fun bindViewPager2( itemClickListener = clickListener, itemLongClickListener = longClickListener, ) - viewPager.adapter = buildAdapter(config, paging, differ) + viewPager.adapter = buildBindingAdapter(config, paging, differ) } else { @Suppress("UNCHECKED_CAST") adapter as BindingRecyclerViewAdapter @@ -95,7 +97,23 @@ fun bindViewPager2( } } -private fun buildAdapter( +/** + * 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. + * + * @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 buildBindingAdapter( config: BindingAdapterConfig, paging: Boolean, differ: DiffUtil.ItemCallback? diff --git a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingPagingRecyclerViewAdapter.kt b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingPagingRecyclerViewAdapter.kt index 1786023..099e7fb 100644 --- a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingPagingRecyclerViewAdapter.kt +++ b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingPagingRecyclerViewAdapter.kt @@ -32,31 +32,70 @@ class BindingPagingRecyclerViewAdapter( ) : PagingDataAdapter(differ), BaseBindingAdapter { + /** + * @see BaseBindingAdapter.getItemInternal + * @see getItem + */ override fun getItemInternal(position: Int): T? = getItem(position) + /** + * @see PagingDataAdapter.onCreateViewHolder + * @see BaseBindingAdapter.onCreateViewHolderInternal + */ override fun onCreateViewHolder(viewGroup: ViewGroup, @LayoutRes layoutId: Int): BaseBindingAdapter.ViewHolder { return onCreateViewHolderInternal(viewGroup, layoutId) } + /** + * @see PagingDataAdapter.onBindViewHolder + * @see BaseBindingAdapter.onBindViewHolderInternal + */ override fun onBindViewHolder(viewHolder: BaseBindingAdapter.ViewHolder, position: Int) { onBindViewHolderInternal(viewHolder, position) } + /** + * @see PagingDataAdapter.onViewAttachedToWindow + * @see BaseBindingAdapter.onViewAttachedToWindowInternal + */ override fun onViewAttachedToWindow(holder: BaseBindingAdapter.ViewHolder) { onViewAttachedToWindowInternal(holder) } + /** + * @see PagingDataAdapter.onViewDetachedFromWindow + * @see BaseBindingAdapter.onViewDetachedFromWindowInternal + */ override fun onViewDetachedFromWindow(holder: BaseBindingAdapter.ViewHolder) { onViewDetachedFromWindowInternal(holder) } + /** + * @see PagingDataAdapter.getItemViewType + * @see BaseBindingAdapter.getItemViewTypeInternal + */ @LayoutRes override fun getItemViewType(position: Int) = getItemViewTypeInternal(position) + /** + * Gets item count and ensures that is is not higher than the [limit] (if set). Else it just returns item count from + * super. + * + * @return [Int] item count + * @see PagingDataAdapter.getItemCount + * @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 build(config: BindingAdapterConfig, differ: DiffUtil.ItemCallback) = BindingPagingRecyclerViewAdapter( itemBinder = config.itemBinder, diff --git a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingRecyclerViewAdapter.kt b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingRecyclerViewAdapter.kt index ddbcf64..8acdea1 100644 --- a/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingRecyclerViewAdapter.kt +++ b/kaal-presentation/src/main/kotlin/cz/eman/kaal/presentation/adapter/BindingRecyclerViewAdapter.kt @@ -5,6 +5,7 @@ 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 @@ -37,8 +38,14 @@ class BindingRecyclerViewAdapter( ) : RecyclerView.Adapter(), BaseBindingAdapter { + /** + * Callback informing that the list has changes. Only as a [WeakReference] to prevent leaks. + */ private val onListChangedCallback: WeakReferenceOnListChangedCallback = WeakReferenceOnListChangedCallback(this) + /** + * List of the items being displayed in this adapter. [ObservableList] supports observing list changes. + */ var items: ObservableList? = null private set @@ -46,33 +53,76 @@ class BindingRecyclerViewAdapter( setItems(items) } + /** + * Gets the specific items from the [items] list. + * + * @see BaseBindingAdapter.getItemInternal + */ override fun getItemInternal(position: Int): T? = items?.get(position) + /** + * Removes the list [onListChangedCallback] when this adapter is detached from the [RecyclerView]. + * + * @param recyclerView to have the listener detached + */ override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { items?.removeOnListChangedCallback(onListChangedCallback) } + /** + * @see PagingDataAdapter.onCreateViewHolder + * @see BaseBindingAdapter.onCreateViewHolderInternal + */ override fun onCreateViewHolder(viewGroup: ViewGroup, @LayoutRes layoutId: Int): BaseBindingAdapter.ViewHolder { return onCreateViewHolderInternal(viewGroup, layoutId) } + /** + * @see PagingDataAdapter.onBindViewHolder + * @see BaseBindingAdapter.onBindViewHolderInternal + */ override fun onBindViewHolder(viewHolder: BaseBindingAdapter.ViewHolder, position: Int) { onBindViewHolderInternal(viewHolder, position) } + /** + * @see PagingDataAdapter.onViewAttachedToWindow + * @see BaseBindingAdapter.onViewAttachedToWindowInternal + */ override fun onViewAttachedToWindow(holder: BaseBindingAdapter.ViewHolder) { onViewAttachedToWindowInternal(holder) } + /** + * @see PagingDataAdapter.onViewDetachedFromWindow + * @see BaseBindingAdapter.onViewDetachedFromWindowInternal + */ override fun onViewDetachedFromWindow(holder: BaseBindingAdapter.ViewHolder) { onViewDetachedFromWindowInternal(holder) } + /** + * @see PagingDataAdapter.getItemViewType + * @see BaseBindingAdapter.getItemViewTypeInternal + */ @LayoutRes override fun getItemViewType(position: Int) = getItemViewTypeInternal(position) + /** + * Gets item count from [items] variable and ensures that is is not higher than the [limit] (if set). Else it just + * returns item count from [items]. + * + * @return [Int] item count + * @see Int.coerceAtMost + */ override fun getItemCount() = (items?.size ?: 0).coerceAtMost(limit ?: Int.MAX_VALUE) + /** + * Allows to set new item list to this adapter. Calculates differences and notifies the adapter about changes. If + * the list has changed, else it does nothing. + * + * @param items new items to be displayed + */ fun setItems(items: Collection?) { if (this.items === items) { return @@ -80,69 +130,161 @@ class BindingRecyclerViewAdapter( val oldItems = this.items if (items == null) { - oldItems?.let { - it.removeOnListChangedCallback(onListChangedCallback) - this.items = null - notifyItemRangeRemoved(0, it.size) - } + handleNewEmptyItems(oldItems) } else { - val newItems = when (items) { - is ObservableList -> items - else -> ObservableArrayList().apply { addAll(items) } - } - newItems.addOnListChangedCallback(onListChangedCallback) + handleNewItems(oldItems, items) + } + } + + /** + * Handles case where new items are empty (null). Removes the [onListChangedCallback], clears current item list and + * notifies using [notifyItemRangeRemoved]. + * + * @param oldItems to have callback removed + */ + private fun handleNewEmptyItems(oldItems: ObservableList?) { + oldItems?.let { + it.removeOnListChangedCallback(onListChangedCallback) + this.items = null + notifyItemRangeRemoved(0, it.size) + } + } + + /** + * Handles new items added to the adapter. First it adds [onListChangedCallback] to new list and then it handles new + * items with multiple cases: + * 1) When [oldItems] are null it sets them to the [items] and notifies using [notifyItemRangeInserted]. + * 2) When [oldItems] are not null and [differ] is not null then new items are handled using [handleNewItemsDiffer]. + * 3) Else items are handles using [handleNewItemsNoDiffer]. + * + * @param oldItems items currently displayed in the list + * @param items new items to be displayed in the list + * @see notifyItemRangeInserted + * @see handleNewItemsDiffer + * @see handleNewItemsNoDiffer + */ + private fun handleNewItems(oldItems: ObservableList?, items: Collection) { + val newItems = when (items) { + is ObservableList -> items + else -> ObservableArrayList().apply { addAll(items) } + } + newItems.addOnListChangedCallback(onListChangedCallback) - if (oldItems == null) { - this.items = newItems - notifyItemRangeInserted(0, newItems.size) + if (oldItems == null) { + this.items = newItems + notifyItemRangeInserted(0, newItems.size) + } else { + if (differ != null) { + handleNewItemsDiffer(oldItems, newItems, differ) } else { - if (differ != null) { - val result = DiffUtil.calculateDiff(DiffCallback(oldItems, newItems, differ)) - oldItems.removeOnListChangedCallback(onListChangedCallback) - this.items = newItems - result.dispatchUpdatesTo(this) - } else { - val oldSize = oldItems.size - val newSize = newItems.size - this.items = newItems - when { - oldSize < newSize -> { - notifyItemRangeChanged(0, oldSize) - notifyItemRangeInserted(oldSize, newSize - oldSize) - } - oldSize > newSize -> { - notifyItemRangeChanged(0, newSize) - notifyItemRangeRemoved(newSize, oldSize - newSize) - } - else -> notifyItemRangeChanged(0, newSize) - } - } + handleNewItemsNoDiffer(oldItems, newItems) + } + } + } + + /** + * Handles new items displayed in the list using a differ. Calculates differences, removes [onListChangedCallback] + * from the [oldItems] list, sets new items to the list and dispatches the updates using [DiffUtil]. + * + * @param oldItems items currently displayed in the list + * @param newItems new items to be displayed in the list + * @param differ used to calculate differences between two lists + * @see DiffUtil.calculateDiff + * @see DiffUtil.DiffResult.dispatchUpdatesTo + */ + private fun handleNewItemsDiffer( + oldItems: ObservableList, + newItems: ObservableList, + differ: DiffUtil.ItemCallback + ) { + val result = DiffUtil.calculateDiff(DiffCallback(oldItems, newItems, differ)) + oldItems.removeOnListChangedCallback(onListChangedCallback) + this.items = newItems + result.dispatchUpdatesTo(this) + } + + /** + * Handles new items displayed in the list without a differ. Handles cases: + * 1) [oldItems] size is lower than [newItems] size + * 2) [oldItems] size is higher than [newItems] size + * 1) [oldItems] size equal to the size of [newItems] + * + * @param oldItems items currently displayed in the list + * @param newItems new items to be displayed in the list + * @see notifyItemRangeChanged + * @see notifyItemRangeInserted + * @see notifyItemRangeRemoved + */ + private fun handleNewItemsNoDiffer(oldItems: ObservableList, newItems: ObservableList) { + val oldSize = oldItems.size + val newSize = newItems.size + this.items = newItems + when { + oldSize < newSize -> { + notifyItemRangeChanged(0, oldSize) + notifyItemRangeInserted(oldSize, newSize - oldSize) + } + oldSize > newSize -> { + notifyItemRangeChanged(0, newSize) + notifyItemRangeRemoved(newSize, oldSize - newSize) } + else -> notifyItemRangeChanged(0, newSize) } } + /** + * Class observing changes in the list and notifying the recycler view about changes. Contains [WeakReference] to + * the adapter which should be notified about list changes. + * + * @param recyclerViewAdapter adapter instance which will be wrapped in [WeakReference] + * @see ObservableList.OnListChangedCallback + * @see ObservableList + */ private class WeakReferenceOnListChangedCallback( recyclerViewAdapter: RecyclerView.Adapter<*> ) : ObservableList.OnListChangedCallback>() { + /** + * [WeakReference] to the adapter which should be notified about list changes. + */ private val adapterReference = WeakReference(recyclerViewAdapter) + /** + * @see ObservableList.OnListChangedCallback.onChanged + * @see RecyclerView.Adapter.notifyDataSetChanged + */ override fun onChanged(sender: ObservableList) { adapterReference.get()?.notifyDataSetChanged() } + /** + * @see ObservableList.OnListChangedCallback.onItemRangeChanged + * @see RecyclerView.Adapter.notifyItemRangeChanged + */ override fun onItemRangeChanged(sender: ObservableList, positionStart: Int, itemCount: Int) { adapterReference.get()?.notifyItemRangeChanged(positionStart, itemCount) } + /** + * @see ObservableList.OnListChangedCallback.onItemRangeInserted + * @see RecyclerView.Adapter.notifyItemRangeInserted + */ override fun onItemRangeInserted(sender: ObservableList, positionStart: Int, itemCount: Int) { adapterReference.get()?.notifyItemRangeInserted(positionStart, itemCount) } + /** + * @see ObservableList.OnListChangedCallback.onItemRangeMoved + * @see RecyclerView.Adapter.notifyItemMoved + */ override fun onItemRangeMoved(sender: ObservableList, fromPosition: Int, toPosition: Int, itemCount: Int) { adapterReference.get()?.notifyItemMoved(fromPosition, toPosition) } + /** + * @see ObservableList.OnListChangedCallback.onItemRangeRemoved + * @see RecyclerView.Adapter.notifyItemRangeRemoved + */ override fun onItemRangeRemoved(sender: ObservableList, positionStart: Int, itemCount: Int) { adapterReference.get()?.notifyItemRangeRemoved(positionStart, itemCount) } @@ -150,6 +292,13 @@ class BindingRecyclerViewAdapter( 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 build(config: BindingAdapterConfig, differ: DiffUtil.ItemCallback?) = BindingRecyclerViewAdapter( itemBinder = config.itemBinder,