1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
/*
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.databinding
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableList
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import com.wireguard.android.BR
import java.lang.ref.WeakReference
/**
* A generic `RecyclerView.Adapter` backed by a `ObservableKeyedArrayList`.
*/
class ObservableKeyedRecyclerViewAdapter<K, E : Keyed<out K>> internal constructor(
context: Context, private val layoutId: Int,
list: ObservableKeyedArrayList<K, E>?
) : RecyclerView.Adapter<ObservableKeyedRecyclerViewAdapter.ViewHolder>() {
private val callback = OnListChangedCallback(this)
private val layoutInflater: LayoutInflater = LayoutInflater.from(context)
private var list: ObservableKeyedArrayList<K, E>? = null
private var rowConfigurationHandler: RowConfigurationHandler<ViewDataBinding, Any>? = null
private fun getItem(position: Int): E? = if (list == null || position < 0 || position >= list!!.size) null else list?.get(position)
override fun getItemCount() = list?.size ?: 0
override fun getItemId(position: Int) = (getKey(position)?.hashCode() ?: -1).toLong()
private fun getKey(position: Int): K? = getItem(position)?.key
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.setVariable(BR.collection, list)
holder.binding.setVariable(BR.key, getKey(position))
holder.binding.setVariable(BR.item, getItem(position))
holder.binding.executePendingBindings()
if (rowConfigurationHandler != null) {
val item = getItem(position)
if (item != null) {
rowConfigurationHandler?.onConfigureRow(holder.binding, item, position)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(DataBindingUtil.inflate(layoutInflater, layoutId, parent, false))
fun setList(newList: ObservableKeyedArrayList<K, E>?) {
list?.removeOnListChangedCallback(callback)
list = newList
list?.addOnListChangedCallback(callback)
notifyDataSetChanged()
}
fun setRowConfigurationHandler(rowConfigurationHandler: RowConfigurationHandler<*, *>?) {
@Suppress("UNCHECKED_CAST")
this.rowConfigurationHandler = rowConfigurationHandler as? RowConfigurationHandler<ViewDataBinding, Any>
}
interface RowConfigurationHandler<B : ViewDataBinding, T> {
fun onConfigureRow(binding: B, item: T, position: Int)
}
private class OnListChangedCallback<E : Keyed<*>> constructor(adapter: ObservableKeyedRecyclerViewAdapter<*, E>) : ObservableList.OnListChangedCallback<ObservableList<E>>() {
private val weakAdapter: WeakReference<ObservableKeyedRecyclerViewAdapter<*, E>> = WeakReference(adapter)
override fun onChanged(sender: ObservableList<E>) {
val adapter = weakAdapter.get()
if (adapter != null)
adapter.notifyDataSetChanged()
else
sender.removeOnListChangedCallback(this)
}
override fun onItemRangeChanged(sender: ObservableList<E>, positionStart: Int,
itemCount: Int) {
onChanged(sender)
}
override fun onItemRangeInserted(sender: ObservableList<E>, positionStart: Int,
itemCount: Int) {
onChanged(sender)
}
override fun onItemRangeMoved(sender: ObservableList<E>, fromPosition: Int,
toPosition: Int, itemCount: Int) {
onChanged(sender)
}
override fun onItemRangeRemoved(sender: ObservableList<E>, positionStart: Int,
itemCount: Int) {
onChanged(sender)
}
}
class ViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)
init {
setList(list)
}
}
|