Dies ist, was ich benutze:
package com.poterion.android.library.adapters
import android.widget.BaseExpandableListAdapter
import io.realm.*
/**
* @author Jan Kubovy <[email protected]>
*/
abstract class RealmExpandableListAdapter<out Group : Any, Item : RealmModel>(
private val itemGroupsProvider: (Item) -> Collection<Group?>,
private val groupsProvider: (Collection<Item>) -> List<Group?>,
private var adapterData: OrderedRealmCollection<Item>?) : BaseExpandableListAdapter() {
private val listener: RealmChangeListener<OrderedRealmCollection<Item>>?
protected val groups: List<Group?>
get() {
return adapterData?.takeIf { isDataValid }?.let(groupsProvider) ?: emptyList()
}
private val isDataValid: Boolean
get() = adapterData?.isValid == true
init {
if (adapterData?.isManaged == false)
throw IllegalStateException("Only use this adapter with managed list, for un-managed lists you can just use the BaseAdapter")
this.listener = RealmChangeListener { notifyDataSetChanged() }
adapterData?.takeIf { isDataValid }?.also { addListener(it) }
}
private fun addListener(data: OrderedRealmCollection<Item>) {
when (data) {
is RealmResults<Item> -> data.addChangeListener((listener as RealmChangeListener<RealmResults<Item>>))
is RealmList<Item> -> data.addChangeListener((listener as RealmChangeListener<RealmList<Item>>))
else -> throw IllegalArgumentException("RealmCollection not supported: " + data.javaClass)
}
}
private fun removeListener(data: OrderedRealmCollection<Item>) {
when (data) {
is RealmResults<Item> -> data.removeChangeListener((listener as RealmChangeListener<RealmResults<Item>>))
is RealmList<Item> -> data.removeChangeListener((listener as RealmChangeListener<RealmList<Item>>))
else -> throw IllegalArgumentException("RealmCollection not supported: " + data.javaClass)
}
}
override fun getGroupCount(): Int = groups.size
override fun getChildrenCount(groupPosition: Int): Int = adapterData?.takeIf { isDataValid }?.let { data ->
val g = groups[groupPosition]
data.filter { g == null || groups(it).contains(g) }.size
} ?: 0
override fun getGroup(groupPosition: Int): Group? = if (groups.size > groupPosition) groups[groupPosition] else null
override fun getChild(groupPosition: Int, childPosition: Int): Item? = children(groupPosition)
.takeIf { it.size > childPosition }?.get(childPosition)
override fun notifyDataSetChanged() {
super.notifyDataSetChanged()
}
private fun children(groupPosition: Int): List<Item> {
return getGroup(groupPosition)
?.let { g -> adapterData?.takeIf { isDataValid }?.filter { groups(it).contains(g) } } ?: emptyList()
}
}
Und Nutzung:
class PersonListAdapter(realm: Realm) :
RealmExpandableListAdapter<String, Person>(
itemGroupsProvider = { person -> arrayOf(person.group, null) },
groupsProvider = { people -> people.map { it.group } },
adapterData = realm.where(Person::class.java)
.findAllSortedAsync("lastName", Sort.ASCENDING, "firstName", Sort.ASCENDING)) {
override fun getGroupId(groupPosition: Int) = getGroup(groupPosition).id
override fun getChildId(groupPosition: Int, childPosition: Int) = getChild(groupPosition, childPosition).id
override fun hasStableIds() = true
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup?): View {
// ... Item View here ...
}
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean,
convertView: View?, parent: ViewGroup?): View {
// ... Group View here ...
}
override fun isChildSelectable(groupPosition: Int, childPosition: Int) = true
}
Ist das für Zukunft in den Plänen? Ich kann es über die Liste tun. Aber das Problem ist, dass, wenn Sie eine sehr große Liste (10.000 + Elemente) haben, es nicht effizient ist, es so zu machen. – KVISH
Wir haben keine aktuellen Pläne, aber ich kann den Anwendungsfall für eine Realm-Version des BaseExpandableListAdapter sehen, die für so etwas benötigt würde. Ich habe es unserem Backlog hinzugefügt: https://github.com/realm/realm-java/issues/1199 –