What is the use of findFirst() method in Realm for Android? Also, how to retrieve the last inserted record from a table using Realm?
findFirst() would be used when you only expect one result from your query, or just don't care about the whole list, and only want to sample one record.
If you want the very last element you could try findAll(), get the size of that list, and get the last element.
Related
I am fetching a list of dogs from an endpoint. Some of the attributes of the dog, color for example, are identified by id. The id's and colors corresponding to the id were all saved in a database when the app is opened. I am using MVVM architecture and assume that the model is consuming the response data correctly.
In the main screen of the app, I have a recyclerView that will populate with a list of dogs. when I fetch the list of dogs, I am returned the id of the dog's color as part of the dog object. The user isn't going want to see the id of the color, but the actual string value of the color corresponding to that id. I need to query the database with that id to get back the string value of the color to display to the UI.
My question is how would I go about doing this? The recyclerView adapter would be where the UI is updated, and I would need the position of the dog to know what color Id I am fetching, but I can't run that query from the adapter as it would lock up the main thread. I thought to create a function in the view model that would update that particular list item, but I think I would still need the position from the adapter. I'm not really sure how to proceed...
I hope my question isn't too confusing, I had a hard time figuring out how to ask! Thanks for your time!
You want to build proper query in your DAO and "join" values from another table, depending on color_id.
You are not allowed to do any queries at adapter level. Data passed to adapter must contain everything you need.
Joins and mappings are described here: https://developer.android.com/training/data-storage/room/accessing-data
In realm we have the option to find the first element in the database using findFirst(). But I want to do the reverse of it. I want to last element based on the some condition which I provide.
To find out the first element in the realm database:
GamesDetail learnGameDetail = realm.where(GamesDetail.class).equalTo("gameType", getResources().getString(R.string.learn_row)).notEqualTo("currentBadge",0).findFirst();
In the above query all the rows will have currentBadge as zero. But the last updated row will have currentBadge with some value. I need to find the last updated row with currentBadge not equal to zero.
Instead of
GamesDetail learnGameDetail = realm.where(GamesDetail.class)
.equalTo("gameType", getResources().getString(R.string.learn_row))
.notEqualTo("currentBadge",0)
.findFirst();
You can do
GamesDetail learnGameDetail = realm.where(GamesDetail.class)
.equalTo("gameType", getResources().getString(R.string.learn_row))
.notEqualTo("currentBadge",0)
.findAll()
.last(null);
Please note that insertion order is not kept after deletion. Using findAllSorted() is generally advised.
Suppose, In my app I have a sqlite table that can contain at most 20 row. Each row has 2 column(id, name). Where I frequently need to search by Id to get Name. For this frequent need I have two solution:
Solution 1: Get rows in a arraylist<model> and then find name from array.
Solution 2: Every time search on sqlite table.
Now please give your opinion which one is better?
Remember again, I need this search in my recycleView item, so it call so frequently.
Thanks
I don't really get what is your real intent, but if your task is to search by id often, I would use
LongSparseArray<String> idsToNames; // or LongSparseArray<Model>
Which will map primitive long to Strings in a more memory-efficient way than Map and will have a better performance than ArrayList when searching.
The advantage over querying SQLite here is that you can do it in a blocking manner instead of having to query database on a background thread every time the lookup runs.
The disadvantage is that whenever data changes in SQLite, you will have to rebuild your idsToNames map. Also, if the number of entries in SQLite will eventually grow, you will end up in a large collection. So I would recommend this approach only if the updates to the database during this session will not happen, and if the data size is always predictable or fixed.
I need to synchronize the data in my application. I do the request to the server, bind and use copyToRealmOrUpdate(Iterable<E> objects) to add or update this data to the database.
But my files can be invalidated and I need something to delete everything that don't have at the data that return at the request. I don't want to truncate or do a manual delete to do this because performance matters.
IDEA 1
#beeender
What do you think about use the PRIMARY_KEY of the table to delete the data that I don't want (or I don't need)?
Looks like:
1º: If the database was populated, get all primary key and add it in an HashMap (or anything that do the same).
2º: Update the data or add, removes the item of the HashMap (using the primary key) if it was updated or added.
3º: Remove all items of HashMap on the Realm.
Maybe the In memory Realm would be a good choice for you in this situation. You can find related documents here .
By using the in-memory Realm:
The db will be empty when you start a new app process
After you close all the instances of the Realm, the data will be cleared as well.
----------------------------------- Update for deleting data for normal case -----------------------------------------
For deleting, there are some options you can use
Remove all data for a specific model, see doc
realm.allObjects(MyModel.class).clear();
Remove entire data from a given Realm by (Realm API)[https://realm.io/docs/java/latest/api/io/realm/Realm.html#deleteRealm(io.realm.RealmConfiguration)] (close all instances first!):
Realm.deleteRealm(realmConfig);
Or just remove the Realm file through normal java API.
If you really care about the performance, you could consider to separate those data in one Realm, and use option 2 or 3 to remove them. See doc here for using different Realm through RealmConfiguration.
----------------------------------- Update for delete by Date field ------------------------------------------------------
For your user case, this would be a good choice:
Add a Date field to your model, and add annotation #Index to make query faster on it.
Update/add rows and set the modified date to current time.
Delete the objects where its modifiedDate is before the current date.realm.where(MyModel.class).lessThan("modifiedDate", currentDate).findAll().clear()
NOTE: "The dates are truncated with a precision of one second. In order to maintain compatibility between 32 bits and 64 bits devices, it is not possible to store dates before 1900-12-13 and after 2038-01-19." See current limitations. If you could modified the table in a very short time which the accuracy doesn't fit, consider to use a int field instead. You can get the column's max value by RealmResult.max()
I already have a SQLite Database setup which I am using as cache for the Android application. The application does a HTTP Request and gets back a List of objects which I can insert into the db. After the first request, if I do anymore requests, how do all of the following in a better way:
1) insert all new objects from the list
2) update all objects that were already in the db
3) delete all rows that were not there in the latest list of objects.
I know that options 1 and 2 can be done using the "INSERT OR UPDATE" query. How can I manage the 3rd option efficiently?
Right now my approach is to delete all from table and then insert all. But that isn't very efficient. Any ideas how to improve it?
For that you can use the ids of the rows. For doing that first retrieve all the rows which you want to delete using SELECT query and add it a temporary arraylist, then use for loop over the arraylist to delete all those rows by using DELETE query.
You should do your operations using the applyBatch() method of the ContentProvider (http://developer.android.com/reference/android/content/ContentProvider.html#applyBatch(java.util.ArrayList)).
You can perform this method in a separate thread asynchronously so that you do not block anything else. You will have to create a list of ContentProviderOperations. In fact, you only need to specify the ones you need to insert or update within the ArrayList and implement the applyBatch() method such that it will automatically delete the rest of the entries in the database.
To answer your question about how to delete the entries not in the table, the logical assumption would be to search through your data sequentially and then delete the ones that do not need to exist.
I guess the intention is to refresh the Http request result set saved in the database. So I think the most efficient way is do a transaction or batch operation to delete all rows from the table first and then insert the new rows. A transaction might be better so that the result rows are either all new or all old, but not mixed.