RealmResults findAllAsync() returns nothing - android

I am new to Realm and I have a problem.
I was able to make some writes using realm.
The problem is that when I try get the RealmResults using
mResults = mRealm.where(Player.class).findAllAsync();
it returns nothing. But when I use
mResults = mRealm.where(Player.class).findAll();
it returns the records.
Can I have some help? Thanks!

As pointed out in the comments, findAllAsync() always returns an empty result. That's what makes it asynchronous! Register a RealmChangeListener to receive the asynchronous result.

Related

Setting global variable with Cloud Firestore on Kotlin

again :) I got a question about Cloud Firestore and Kotlin.
I need to get data from firestore with some code like this:
{
val comments = mutableListOf<Comment>()
val firestore = FirebaseFirestore.getInstance()
firestore.collection(collection).document(documentID).collection("comments")
.addSnapshotListener { querySnapshot, firebaseFirestoreException ->
comments = querySnapshot?.toObjects(Comment::class.java)!!
// do something with 'comments'. Works: comments is populated
}
// do something with variable 'comments'. Doesn't work: comments is now empty
}
The variable 'comments' gets populated inside the listener curly brackets but when the listener ends, the value goes back to 0.
I've researched online and found examples in JAVA that works perfectly this way, for example:
https://youtu.be/691K6NPp2Y8?t=246
My purpose is to fetch data only ONCE from the Cloud Firestore and store that value in a global variable, comments.
Please, let me know if you have a solution for this.
Thank you.
The value doesn't "go back to zero". You should understand that the database query is asynchronous, and addSnapshotListener returns immediately, before the query completes. The final value is only known when the listener is invoked some time later.
Also, you should know that if you just want to query a single time, you should use get() instead of addSnapshotListener(). It is also asynchronous and returns immediately, and the Task it returns will get invoked some time later. There are no synchronous options that block the caller until the query is complete - you will need to learn how to do your work asynchronously.

Android - Room Persistence Library - Access data both synchronously & through observer based on need

Problem:
I am using Room Persistence Library and so far everything is working fine except that there is a data from select query which I need synchronously as I am calling it from a Periodic Job (Work Manager's Worker). I have defined the return type to be LiveData as I am also accessing it for display purposes in UI and so observers are great for that but now I also need the same data in Job.
Code Snippet
#Query("SELECT * from readings ORDER BY date, time ASC")
LiveData<List<Reading>> getAllReadings();
Tried
I have tried the getValue() method in LiveData but it returns null as the data is not loaded in LiveData while making the query.
readingDao().getAllReadings().getValue() // returns null
Possible Solution
There is only one solution that I can think of which is to duplicate the getAllReadings query with a different name and return type (without LiveData) but I don't think this is a clean approach as it increases duplication of code just to get a synchronous return type.
Please let me know if there is any other solution or perhaps some way to synchronously access data from LiveData variable.
You can allow main thread query when you initialize Room DB, but it's clearly not desirable. This will give you the synchronous behavior but will block user interface. Is there a specific reason you want this to be synchronous?
The reason why getValue() is returning null is because Room is querying data asynchronously. You can attach an observer or a callback function to get result when the query is finished. You can display the result to the UI or chain another call for sequential operation etc from there.
I use RxJava to wrap my query request for asynchronous query but I you can also use AsyncTask.

How to know whether realm.commitTransaction() succefull

In my application I'm inserting user like below
realm.beginTransaction();
realm.copyToRealmOrUpdate(user);
realm.commitTransaction();
I want to display and message if data inserted correctly. How to check if data insertion works successfully or not.
I know if I use realm.executeTransactionAsync() method I can get callback for onSuccess() and onError(). But It does not make any sense to insert one object asynchronously just to get access in to onSuccess().
The line realm.copyToRealmOrUpdate(user); will return an object of type user which is managed by realm signifying that it got inserted. If that object is null that would imply that the transaction did not succeed in which case it would have crashed with an exception.

How to convert RealmResults<Object> to List<Object>

I have RealmResults that I receive from Realm like
RealmResults<StepEntry> stepEntryResults = realm.where(StepEntry.class).findAll();
Now I want convert RealmResults<StepEntry> to ArrayList<StepEntry>
I have try
ArrayList<StepEntry> stepEntryArray = new ArrayList<StepEntry>(stepEntryResults));
but the item in my ArrayList is not my StepEntry object, it is StepEntryRealmProxy
How can I convert it?
Any help or suggestion would be great appreciated.
To eagerly read every element from the Realm (and therefore make all elements in the list become unmanaged, you can do):
List<StepEntry> arrayListOfUnmanagedObjects = realm.copyFromRealm(realmResults);
But you generally have absolutely no reason to do that unless you want to serialize the objects with GSON (specifically, because it reads field data with reflection rather than with getters), because Realm was designed in such a way that the list exposes a change listener, allowing you to keep your UI up to date just by observing changes made to the database.
The answer by #EpicPandaForce works well. I tried this way to optimize my app performance and I find the following is a bit faster. Another option for people who prefer speed:
RealmResults<Tag> childList = realm.where(Tag.class).equalTo("parentID", id).findAll();
Tag[] childs = new Tag[childList.size()];
childList.toArray(childs);
return Arrays.asList(childs);
In Kotlin:
var list : List<Student>: listof()
val rl = realm.where(Student::class.java).findAll()
// subList return all data contain on RealmResults
list = rl.subList(0,rl.size)

What happened to removing items from realm.io? RealmException "Removing object is not supported."?

I am trying to delete the last Object from the Realm.io database based on a query, like so:
Realm realm = Realm.getInstance(this);
final RealmResults<RealmCustomLocation> databaseLocations = realm.where(RealmCustomLocation.class).findAllSorted("timeStamp", RealmResults.SORT_ORDER_DESCENDING);
if(databaseLocations.size() >= 4){
realm.beginTransaction();
databaseLocations.removeLast();
realm.commitTransaction();
}
This is exactly like what is written at the Realm.io instructions about deletion:
realm.beginTransaction();
result.removeLast();
realm.commitTransaction()
But when I execute the code it always breaks with a RealmException
io.realm.exceptions.RealmException: Removing object is not supported.
Then I looked at the source code of RealmResults.java and I find this:
So no wonder it keeps crashing, removeLast() does nothing, only throw an error!
So my question is: How can I remove an object from the database then?!
I am using realm.io 0.77 (compile 'io.realm:realm-android:0.77.0') on Android.
I appreciate your help on this!
I have contacted Realm.io support, awaiting an answer. For the meantime:
RealmCustomLocation location = databaseLocations.get(databaseLocations.size() - 1);
location.removeFromRealm();
works equivalent to
databaseLocations.removeLast()
so it can be used as a workaround.
Edit: Support told me that they are fixing it for future versions and recommended to use the workaround I posted for in the mean time.
If you want to delete all objects, then I would create a while loop like this:
while (location.size() > 0) {
location.removeLast();
}

Categories

Resources