Android Livedata Room. Which method to use - android

In my Android Kotlin App. User profile (A form) needs to be updated using data from RestAPI eg. education and location data from API looks like this
{"educations": [{"edu_uid": 123, "edu_sector": "xxxx", "edu_degree": "xxx"}, .....}
{"locations": [{"loc_uid": 123, "loc_place": "xxxx", "loc_zip": "xxx"}, .....}
After consuming this data. We show it in an adapter. User choose his choice. We update XML views like #id/textViewEduSector and #id/textViewEduDegree. After filling up the form, When the User submit data I send only "edu_uid" "loc_uid" to the Server. Here is representation of my implementation:
profile_fragment -> education_fragment -> education_adapter onEducationClick ->
navigateUp() -> profile_fragment update #id/textViewEduSector and #id/textViewEduDegree.
Then location and so. At the end when User submit the form,how can I pick "edu_uid" and "loc_uid" to sendback data to API endponit eg. "/profile/update".
How can I collect these uids temporarily. I have a Room database with all User fields. Here I donot want to retain hidden fields, "edu_uid" or "loc_uid". Is it necessary to update Room via Dao and then picking data from there and sent to API or any other workaround.? Fast and efficient?

Since it is hard to get the point of your problem, i try to give my general thoughts about your use-case.
Try to separate next issues:
What is single source of truth in your app? Is it a local database? If not - why?
How to represent you data sources in UI?
How to synchronise your data structures with server?
Data structures. Try to use a database (ROOM) as a single source of truth in your app. If you do, you get additional benefits of working without access to Rest API. In this case your ROOM-entities set should include - Education (edu_uid as Primary Key), Location (loc_uid as Primary Key) and User/UserProfile (with edu_uid and loc_uid as Foreign keys). In this case you should't add fields "edu_sector" or "edu_degree" to UserProfile data class. And with a action "submit" you have to save changes to your local database (with edu_id and loc_uid) and to solve your "REST API-question" at next step.
Representation in UI. If you use MVVM, you should't have a problems with "edu_id" or "loc_id". You declare references to Education and Location in your ViewModel and in your XML you can easy consume any fields of these objects.
Sync with server. It should be easy if you have efficient local database with all needed fields as foreign keys (again in your DAO you can get all the rest fields you want from other tables with table joins)
Again, maybe I didn't get your real problem. It is really unclear

Related

Firebase Database: get all child's data from childs

I want to be able to differentiate my content between type and get all other data but I don't know how to get past the IDs after content.
I want every data from -NBC22CHEk3ebNxdlYOi, -NBC-Nfz6e5yppFlxU7S, -NBC1TVY-TzT7yfrSA3o
and later be possible to get new video id's from existing and new users
/content/{user_uid}/{content_uid}
If I want only the content from one user then I can write this:
val uid = FirebaseAuth.getInstance().uid
// url is just a placeholder for the real database url
val ref = FirebaseDatabase.getInstance(url).getReference("/content/$uid")
I want all content with the type value "video" from all users.
That's actually not possible with your actual database structure. All queries in the Realtime Database work on a flat list of nodes, where the value on which you want to perform the filter/order on, must be at a fixed path under each direct child node.
Unfortunately, that's not your case, because you have a dynamic key under the content node, which is actually the UID, and which also means that you can't filter on type. If you want to allow that, then you have to create a flat list of videos, where the UID (SIH5...89j1) is a property inside each video object. This is already achieved since publisher_uid holds exactly that.
In short, remove the extra (UID) level from your database tree. Or, leave it as it is, and denormalize the data. Basically create a new structure like this:
/content/{content_uid}
See, there is no UID involved. If you're new to NoSQL databases, this might sound some kind of weird, but it's actually a quite common practice.

How to manage data in an offline Android app in kotlin?

I want to make an android app that works offline. For the data part, I want to have some data in a json file, and whenever my app is open firstly that JSON file is fetched, and from the fetched data I want to make tables entries in android room database(offline). So that, let say if user liked some quotes, then i can change the state of that quote as liked in room db, and when user clicked on Liked Quotes navigation, I can show those offline stored quotes which were liked (OfCourse when user delete the app that data will be lost). The problem I'm facing is where to fetch that data file and create entries in room db. If I do this in onCreate() then whenever user will open this app the duplicate entries will be created everytime. How to make those entries only ones?
There's several ways to do it. One way is to include a random UUID in each element, and make that column in the DB have a UNIQUE constraint. Then re-adding it will fail (alternatively you can use an UPSERT and then it will automatically update the data in case the data changed).
Another way is to just not process the file if it already exists in onCreate. Your logic can be
if(network_exists) {
copy_file_from_network()
}
else if(json file exists) {
return
}
else {
copy_file_from_assets()
}
process_json_file()
Actually I can see a good argument for doing both- that way if there are updates to existing rows you process them, but if there's no new data you don't waste your time.
As for a good place to put this- I'd be running this during your splash screen if you have one, so the user has an indication that you may be processing for a while.

Change Firebase Realtime Database POJO properties using #PropertyName, How to migrate existing data

I have an app already in production, and now I want to change database property names in several tables to reduce bandwidth.
For eg, realtime database existing property is:
purchasePrice: 60
and by using #PropertyName, I want to change it so it now looks like this:
pp: 60
The changed POJO now has #PropertyName like:
#PropertyName("pp")
public float purchasePrice;
The question is: What is the best migration strategy so that all existing 'purchasePrice' is updated to new name in the realtime database, i.e 'pp' in this example case?
One naive approach I can think of is, on app update at client end, pull all data using old POJOs and assign each property to new POJOs (newPOJO.pp = oldPOJO.purchasePrice) and then save it in DB. But there should be a better way, as I have many POJOs.
Thanks,
If you want to change the name of a field in the database everywhere it occurs, there is really no easy way to do this. You're going to have to:
Query all of the nodes where it could appear
Check to see if the field needs to change
Write the new data back to that location
Whether you do that with code that uses #PropertyName or something more generic, it doesn't really matter.

Can Firebase return only some of the attributes? [duplicate]

Is there any way to select specific properties from firebase Realtime Database? I know there is a way to retrieve selected properties from firestore but how can get via Realtime database using Node.js
I want only Notes from everyone nothing else.
Suppose i just want to select Notes from Allergy here is my sample code which i tried but not successes...
admin.database().ref(`vitals/Allergy`).select('Notes').then(result => {//here is my result.....})
But it shows me that select is not a function.......
Realtime Database doesn't support "projections" like this (neither does Cloud Firestore). If you are going to query across multiple child nodes, you are going to get each entire child node that matches the query. Even if you want just one property of each child, you can't avoid the cost of downloading the entire child.
If your app is very sensitive to performance on these types of queries, consider duplicating the data such that there is another branch of your database that contains only the "Notes" property, and query that branch alone. This duplication is common in NoSQL type databases, and is call the "fan out" technique.
If you want to save download band then i can't help you further, otherelse:
let ArrayOfAllDownloadedNotes = [];
firebase.database().ref('yourRootFolders/vitals/Allergy').once((snapshot)=>{
ArrayOfAllDownloadedNotes = [...ArrayOfAllDownloadedNotes, snapshot.val().Notes];
});
//Reapeat the firebase formula for every child you want retrieve the Notes from
//You may also use forEach((item)=>{}) function for each folder you want to retrieve the //notes from if you want
console.log(My Array of Notes:',ArrayOfAllDownloadedNotes );

copyToRealmOrUpdate and Delete

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

Categories

Resources