2015-05-29 21 views
5

Próbuję użyć magazynu danych realm dla systemu Android i próbuję utworzyć aplikację, która pokazuje użytkownikowi listę opcji w ListView, takich jak lista kontaktów użytkowników. Pierwsza litera każdej sekcji (np. A, B, C itd.) Powinna być nagłówkiem. Czy jest sposób na osiągnięcie tego celu za pomocą RealmBaseAdapter?RealmBaseAdapter z nagłówkami sekcji

Obecnie mam to działa z ArrayAdapter i po prostu mam tablicę z wartościami, ale chciałbym pobrać dane z Realm za pomocą adaptera, jeśli to możliwe. Wiem, że w iOS jest to dość proste przy użyciu NSFetchedResultsController. Jak rozbijamy RealmResults na sekcje?

Odpowiedz

2

RealmBaseAdapter nie działa z ExpandableListAdapter (co zakładam, że używasz dla sekcji?), Więc teraz twoim jedynym wyborem jest stworzenie własnej implementacji. Ale RealmResults jest również listą, więc powinien działać bezproblemowo z ArrayAdapter.

Można również zobaczyć więcej szczegółów tutaj: https://github.com/realm/realm-java/issues/978

+0

Czy to w planach na przyszłość? Mogę to zrobić za pomocą listy. Ale problem polega na tym, że gdy masz bardzo dużą listę (ponad 10 000 przedmiotów), nie jest to skuteczne. – KVISH

+0

Nie mamy żadnych aktualnych planów, ale widzę przypadek użycia dla Realmowej wersji BaseExpandableListAdapter, która byłaby potrzebna do czegoś takiego. Dodałem go do naszych zaległości: https://github.com/realm/realm-java/issues/1199 –

0

To co mam użyć:

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() 
    } 
} 

i użytkowania:

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 
} 
Powiązane problemy