2015-05-29 4 views
5

Ich versuche, den realm Datenspeicher für Android zu verwenden, und ich versuche, eine Anwendung zu erstellen, die dem Benutzer eine Liste der Optionen in einer ListView zeigt, die der Kontaktliste des Benutzers ähnlich ist. Der erste Buchstabe für jeden Abschnitt (wie A, B, C usw.) sollte ein Header sein. Gibt es eine Möglichkeit, dies mit RealmBaseAdapter zu erreichen?RealmBaseAdapter mit Abschnittsüberschriften

Zur Zeit habe ich es mit ArrayAdapter arbeiten und ich habe einfach ein Array mit Werten gefüllt aber würde gerne Daten aus Realm mit seinem Adapter ziehen, wenn möglich. Ich weiß, in iOS ist dies ziemlich einfach mit der NSFetchedResultsController. Wie trennen wir die RealmResults in Abschnitte?

Antwort

2

RealmBaseAdapter funktioniert nicht mit ExpandableListAdapter (von dem ich annehme, dass Sie für Abschnitte verwenden?), So dass Sie jetzt nur Ihre eigene Implementierung erstellen können. Aber ein RealmResults ist auch eine Liste, also sollte es nahtlos mit einem ArrayAdapter funktionieren.

können Sie hier weitere Informationen siehe auch: https://github.com/realm/realm-java/issues/978

+0

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

+0

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 –

0

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 
} 
Verwandte Themen