لذلك ، وصلت أخيرًا إلى تتويج فكرتي بمكتبة تتضمن منطق اختيار العناصر من قائمة في محول. بعد حل مستقلة منصة و مكتبة على أساس LiveData ، كتبت شيئا لمساعدة لك بسرعة وسهولة ربط كل هذا إلى محول للحد من التعليمات البرمجية بشكل عام.
واجهة SelectingListAdapter
لنبدأ بواجهة SelectingListAdapter البسيطة التي أضفتها لمحول بقائمة خطية عادية. في تجربتي ، يتم بيع ما بين 90-95٪ من المحولات بهذا الشكل.
interface SelectingListAdapter<T> {
fun setListItems(items: ArrayList<T>)
}
لا شيء معقد - فقط تحديث قائمة العناصر. وفي رأيي ، لن يكون من الصعب إضافة هذه الواجهة إلى قائمة تلك المطبقة في محولك. لماذا؟ حتى تتمكن من استخدام كلتا طريقتي التمديد ، والتي سأشير إليها بعد ذلك:
fun <T> SelectingListAdapter<T>.observeItemsChange(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<T>) {
liveDataSource.allItems.observe(lifecycleOwner, { items -> setListItems(items) })
}
الطريقة observeItemsChangeتشترك في التغييرات على قائمة العناصر في LiveDataSource.
fun RecyclerView.Adapter<*>.observeSelectionChange(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<*>) {
liveDataSource.observeSelectionChange(lifecycleOwner) { position, _ ->
notifyItemChanged(position)
}
}
الطريقة observeSelectionChangeتشترك بالفعل في التغييرات في اختيار العناصر. هنا لا يوجد سوى إشعار بأن العنصر بحاجة إلى التحديث. سيتم وصف التحقق مما إذا كان هذا العنصر محددًا بالفعل أدناه.
fun <T, TAdapter> TAdapter.observeAllChanges(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<T>)
where TAdapter : RecyclerView.Adapter<*>,
TAdapter : SelectingListAdapter<T> {
observeSelectionChange(lifecycleOwner, liveDataSource)
observeItemsChange(lifecycleOwner, liveDataSource)
}
حسنًا ، إذا كنت تريد استدعاء كلتا الطريقتين في وقت واحد ، فهناك طريقة observeAllChangesستقوم بذلك في سطر واحد.
فئة BaseSelectingListAdapter
, LiveDataSource, . , :
abstract class BaseSelectingListAdapter<T, VH: BaseSelectingListHolder<T>>
: RecyclerView.Adapter<VH>(), SelectingListAdapter<T> {
var callback: SelectingListAdapterCallback? = null
...
}
abstract class BaseSelectingListHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bindItem(item: T, isSelected: Boolean, onClick: (() -> Unit)?)
}
, SelectingListAdapterCallback.
interface SelectingListAdapterCallback {
fun isItemSelected(position: Int): Boolean
fun clickItem(position: Int)
}
, , , .
BaseSelectingListAdapter , LiveDataSource.
fun <T> setCallback(liveDataSource: LiveDataSource<T>) {
callback = object : SelectingListAdapterCallback {
override fun isItemSelected(position: Int) =
liveDataSource.isItemSelected(position)
override fun clickItem(position: Int) {
liveDataSource.clickPosition(position)
}
}
}
BaseSelectingListAdapter — , .
fun fullyInitialize(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<T>) {
observeAllChanges(lifecycleOwner, liveDataSource)
setCallback(liveDataSource)
}
fullyInitialize, . . , , .
onCreateViewHolder bindItem. -, boilerplate .
class MyAdapter : BaseSelectingListAdapter<User, MyHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
MyHolder(...)//create your holder view
}
class MyHolder(itemView: View) : BaseSelectingListHolder<User>(itemView) {
override fun bindItem(item: User, isSelected: Boolean, onClick: (() -> Unit)?) {
//bind your data
}
}
, . - , , :
- .
- ( , ),
SelectionManager'.
:
الروابط في Gradle:
implementation 'ru.ircover.selectionmanager:core:1.1.0'
implementation 'ru.ircover.selectionmanager:livesource:1.0.1'
implementation 'ru.ircover.selectionmanager:selectingadapter:1.0.0'