realm-java
realm-java copied to clipboard
Merge two RealmResult
We LOVE to help with any issues or bug you have!
Questions: If you have questions about how to use Realm, please ask on SO - we monitor the Realm tag.
Feature Request: Just fill in the first two sections below.
Bugs: To help you as fast as possible with an issue or bug please describe your issue and the steps you have taken to reproduce it in as many details as possible.
Thanks for helping us help you :-)
Remove this and above before submitting.
Goal
What do you want to achieve? I want to merge two result of Table User in RealmResult.
RealmResults<User> r1 = realm.where(User.class) .equalTo(some condition) .findAllSorted("timestamp", Sort.ASCENDING);
RealmResults<User> r2 = realm.where(User.class) .equalTo(some condition) .findAllSorted("timestamp", Sort.DESCENDING);
Expected Results
r=r1+r2
?
Actual Results
E.g. full stack trace with exception
Steps & Code to Reproduce
Describe your current debugging efforts.
Code Sample
> Your code here. Bigger samples should ideally be as separate Android Studio project,
> in gists/repositories or privately at [email protected])
Version of Realm and tooling
Realm version(s): ? 2.2.1
Realm sync feature enabled: yes/no don't know Android Studio version: ? 2.3
Which Android version and device: ? 6 Moto X Play
Hi @DastanIqbal
Interesting, sort of like a CompositRealmResults
, but can you explain more about your use case?
- Should the merged result be auto-updated?
- How should the elements be merged? Just
[result1, result2]
or possibly mixed somehow?
Note, it can already be accomplished today using:
List<User> combined = new ArrayList();
combined.addAll(result1);
combined.addAll(result2);
You would miss out on some of the RealmResults
special features, though.
@DastanIqbal You are looking for http://stackoverflow.com/a/34976540/2413303 (although he is missing the RealmChangeListener
)
Realm Core does not provide this functionality currently.
Thanks for the response guys.
@cmelchior Should the merged result be auto-updated? ya it will but the end result will be result1+result2.
How should the elements be merged? Just [result1, result2] or possibly mixed somehow?
No, it will be just result1+result2.
Actually my first result1, Users based on status like new,ongoing in ascending order(by timestamp) and then result2, Users based on status like canceled,resolved in descending order(by timestamp).
its means new,ongoing will be on top, and then others.
and my RecylcerViews Adapter are total depend on RelamResult. so I can't use ArrayList for now.
@Zhuinden Ya I am using RealmChangeListener
when anything changes in list.
@kneth Thanks kneth, but Can you consider this issue in future release build?
You could conceivably implement this yourself, by creating a CompositeRealmResults
class that extended RealmResults
and accepts two or more RealmResults as input. You would then need to override all methods to account for the change in semantics, e.g addChangeListener
should add the listener to more than one RealmResults
, first()
should only pick the result from the first RealmResults and so on.
I won't rule out we can provide an implementation of this at one point, but it will unfortunately not have a high priority unless there is a big demand for it.
k thanks @cmelchior let me try what you explained
And realm is awesome. :)
@cmelchior RealmResults is a final class, can't extend.
It was made non-final in 2.2.2
@DastanIqbal no it's not since I think something like Realm ~~2.2.0~~ 2.2.2
But even then, you conveniently skipped this answer http://stackoverflow.com/a/34976540/2413303
@Zhuinden I checked that answer, but not helping, my adapter using RealmResult, cannot migrate to List. :(
That statement is false.
@cmelchior How do I access BaseRealm its local class, require in constructor and constructor is also local. v3.0.0
Just created local package io.realm
, everything is accessible now.
@DastanIqbal Any progress? I'm interested in what you were able to implement.
I have a use case for this also; 'pinning' items to the top of an adapter.
Hi @rscottcarson, Sorry for late reply,
I used Arraylist to combined the result as @cmelchior mentioned in above comment
public ArrayList<RealmResults<Bean>> getXObject() {
RealmResults<Bean> withName = realm.where(Bean.class).isNotNull("name").findAllSorted("name");
RealmResults<Bean> withOutName = realm.where(Bean.class).isNull("name").findAllSorted("phoneno");
ArrayList<RealmResults<Bean>> xInvites = new ArrayList<>();
xInvites.add(withName);
xInvites.add(withOutName);
return xInvites;
}
and I used @Zhuinden link modified little for RealmAdapter
public abstract class RealmMultiAdapter<T extends RealmObject> extends RecyclerView.Adapter {
protected List<RealmResults<T>> realmResults;
protected Context context;
private RealmBaseAdapter<T> realmBaseAdapter;
public RealmMultiAdapter(Context context) {
this.context = context;
}
public void setRealmList(List<RealmResults<T>> realmResults) {
this.realmResults = realmResults;
}
/**
* Returns how many items are in the data set.
*
* @return count of items.
*/
public int getCount() {
if (realmResults == null) {
return 0;
}
int count = 0;
for (RealmResults<T> realmResult : realmResults) {
count += realmResult.size();
}
return count;
}
/**
* Returns the item associated with the specified position.
*
* @param i index of item whose data we want.
* @return the item at the specified position.
*/
public T getItem(int i) {
if (realmResults == null || realmResults.size() == 0) {
return null;
}
int count = 0;
for (RealmResults<T> realmResult : realmResults) {
if (i < realmResult.size() + count) {
return realmResult.get(i - count);
}
count += realmResult.size();
}
return null;
}
/**
* Returns the current ID for an item. Note that item IDs are not stable so you cannot rely on the item ID being the
* same after {@link #notifyDataSetChanged()} or {@link #updateRealmResults(List<RealmResults<T>>)} has been called.
*
* @param i index of item in the adapter.
* @return current item ID.
*/
@Override
public long getItemId(int i) {
// TODO: find better solution once we have unique IDs
return i;
}
/**
* Updates the RealmResults associated to the Adapter. Useful when the query has been changed.
* If the query does not change you might consider using the automaticUpdate feature.
*
* @param queryResults the new RealmResults coming from the new query.
*/
public void updateRealmResults(List<RealmResults<T>> queryResults) {
this.realmResults = queryResults;
notifyDataSetChanged();
}
public RealmBaseAdapter<T> getRealmAdapter() {
return realmBaseAdapter;
}
public void setRealmAdapter(RealmBaseAdapter<T> realmAdapter) {
realmBaseAdapter = realmAdapter;
}
}
then after you can extend RealmMultiAdapter with your adapter.
public class BeanAdapter extends RealmMultiAdapter<Bean>{
after that same rule as you follow for other realm adapter.
PS: I was expecting something else, but I compromised with this solution.
EDITED according to @Zhuinden I know this may look very hacky but this is how I managed to do it:
public Observable<ArrayList<Project>> getUserProjects(int userId) {
return getDatabase()
.where(User.class)
.equalTo("id", userId)
.findFirstAsync()
.asObservable()
.doOnUnsubscribe(()->closeConnections(1))
.filter(result -> result.isLoaded() && result.isValid())
.cast(User.class)
.map(user -> {
ArrayList<Project> projects= new ArrayList<>();
projects.addAll(user.getProjectsJoined());
projects.addAll(user.getProjects());
Collections.sort(projects, (o1, o2) -> -o1.getCreatedAt().compareTo(o2.getCreatedAt()));
return projects;
});
}
I don't see why you would map them to a RealmList
if it's not actually a managed link between managed objects.
It would make more sense for it to be
List<Project> projects = new ArrayList<>(user.getProjectsJoined().size() + user.getProjects().size());
You're absolutely right. I just did it that way because all of my adapters inherit from RealmAdapter, I know ArrayList is lighter... I am not even using auto update... otherwise it wouldn't have made any sense.
Another use case: showing user search results, with any matching at the start showing first, and any matching anywhere in the word showing second.
➤ Edwin Monk-Fromont commented:
Another use case: showing user search results, with any matching at the start showing first, and any matching anywhere in the word showing second.
I have a use case for this also; 'pinning' items to the top of an adapter.
Yes i have the same requirement, do we have any direct method available from realm other than the workarounds suggested by DastanIqbal commented on May 23, 2017