问题
I have a RealmResults object which holds output of a .where.findAll() query. I am showing contents of this object in a RecyclerView, but since the contents of the RealmResults object are static, it shows same set of records evertime the RecyclerView is opened. I want to shuffle (randomize) the contents of RealmResults so that I can show different values that are in the RealmResults in my RecyclerView. Please suggest some possible ways in which I can perform the same.
回答1:
You should not randomize the list itself, you should randomize your access of it (the indices).
Build a list that contains the indexes from [0, n-1]
List<Integer> indices = new ArrayList<>(realmResults.size());
for(int i = 0; i < realmResults.size(); i++) {
indices.add(i);
}
Shuffle it
Collections.shuffle(indices);
Then when you pick the view holder data, index realm results with indexed random position
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(holder instanceof YourHolder) {
YourHolder yourHolder = (YourHolder) holder;
RealmData realmData = realmResults.get(indices.get(position));
//init data for your holder
}
}
回答2:
For future references, when extending RealmRecyclerViewAdapter
, if you enabled the autoUpdate feature, the above solution will not be enough in cases of updates.
Here is a solution based on the same idea, handling the updates.
Here I ignore the update type and just reset the whole shuffling state if the item count changes. It's not hard to adapt for more specific events (itemRangeAdded, itemRangeRemoved, ...) you just need to update indicesMapList
and displayedMapList
accordingly.
This adapter handles shuffling/sorting and is ready to handle filtering as well (it was not asked but pulled this from a code I did, you can remove unnecessary part if not wanted).
(To filter just update the displayedMapList
with indices of items you want to display, sort/shuffle operations will preserve the filter)
abstract class BaseRealmAdapter<T : RealmObject, S : RecyclerView.ViewHolder>(data: OrderedRealmCollection<T>,
autoUpdate: Boolean) :
RealmRecyclerViewAdapter<T, S>(data, autoUpdate) {
private val indicesMapList = arrayListOf(*(0 until getRealItemCount()).toList().toTypedArray())
val displayedMapList = ArrayList(indicesMapList)
var shuffled = false
private set
/** Displayed item count (after possible filter) */
override fun getItemCount() = displayedMapList.size
override fun getItem(index: Int) = super.getItem(displayedMapList[index])
/** Unfiltered item count */
fun getRealItemCount() = super.getItemCount()
fun shuffle() {
if (getRealItemCount() == 0)
return
shuffled = true
Collections.shuffle(indicesMapList)
// Keep same order
displayedMapList.sortBy { indicesMapList.indexOf(it) }
notifyDataSetChanged()
}
fun sort() {
if (getRealItemCount() == 0)
return
shuffled = false
indicesMapList.sort()
displayedMapList.sort()
notifyDataSetChanged()
}
protected fun resetIndicesMap(notifyDataSetChanged: Boolean = true) {
shuffled = false
indicesMapList.clear()
indicesMapList.addAll(0 until getRealItemCount())
resetDisplayedList()
if (notifyDataSetChanged)
notifyDataSetChanged()
}
protected fun resetDisplayedList() {
displayedMapList.clear()
displayedMapList.addAll(indicesMapList)
}
protected fun getIndicesMapList() = ArrayList(indicesMapList)
override fun onAttachedToRecyclerView(recyclerView: RecyclerView?) {
registerAdapterDataObserver(DataObserver())
super.onAttachedToRecyclerView(recyclerView)
}
/** This implementation will cancel any current shuffled state when adding items */
inner class DataObserver : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
// Item(s) added or removed: this will cancel filtering
if (getRealItemCount() != indicesMapList.size)
resetIndicesMap(true)
}
}
}
来源:https://stackoverflow.com/questions/36241590/how-can-i-shuffle-the-contents-of-a-realmresults-object