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.
Related
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
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 );
I have a database schema where i am loading a bunch of clients from a server with data such as first name, last name and id into my db when the app starts. THis data is then displayed in a list format to the user. I have another tab in my app that switches to a view which shows the client list sorted by id into sections similar to the people app with section headers. The trouble is, the user can switch to the sorted list tab immediately upon startup and that list relies on the db already being populated with client objects. It would be making a query on an empty db if the user switches immediately. Is there any way to block that call until the db is fully loaded with the client data? I know java has synchronized methods, so can i sync on the db query or do anything like that?
The easiest is to add an isReady boolean and to loop it is true (assuming a seperate thread is populating the db). Alternatively you can disable the button until it is ready, which is a better solution.
I currently successfully use a SQLite database which is populated with data from the web. I create an array of values and add these as a row to the database.
Currently to update the database, on starting the activity I clear the database and repopulate it using the data from the web.
Is there an easy method to do one of the following?
A: Only update a row in the table if data has changed (I'm not sure how I could do this unless there was a consistent primary key - what would happen is a new row would be added with the changed data, however there would be no way to know which of the old rows to remove)
B: get all of the rows of data from the web, then empty and fill the database in one go rather than after getting each row
I hope this makes sense. I can provide my code but I don't think it's especially useful for this example.
Context:
On starting the activity, the database is scanned to retrieve values for a different task. However, this takes longer than it needs to because the database is emptied and refilled slowly. Therefore the task can only complete when the database is fully repopulated.
In an ideal world, the database would be scanned and values used for the task, and that database would only be replaced when the complete set of updated data is available.
Your main concern with approach (b) - clearing out all data and slowly repopulating - seems to be that any query between the empty and completion of the refill would need to be refused.
You could simply put the empty/repopulate process in a transaction. Thereby the database will always have data to offer for reading.
Alternatively, if that's not a viable solution, how about appending newer results to the existing ones, but inserted as with an 'active' key set to 0. Then, once the process of adding entries is complete, use a transaction to find and remove currently active entries, and (in the same transaction) update the inactive entries to active.
I have an application that uses a pre-polulated database to list events. The app allows people to save these events to their favorites by setting a '1' to the column isFavorite. Then the user can view only a list of 'favorited' events which searches for all rows that have isFavorite = 1.
If any changes happen to the events or I need to add more to the list, I have to make those changes and then push the update to the app which completely writes over the table, clearing out their favorites.
Is there any way that I can, on upgrade, save a list of id's of all the events that they have set to their favorites, then after the new database has been loaded, to set all id's in that list to 1 so the user doesn't lose their favorited data?
If there are any other better solutions to this problem I would really appreciate it, this has been the biggest hurdle for me so far.
I guess, you have a SQLiteOpenHelper-class? This class must be extended and then provides two functions: onCreate (which is called when the Database is queried and it doesn't exist (Normally creates your Database in the first place)) and onUpdate (which is queried when the Database structure should be updated).
The onUpdate-method has an SQLiteDatabase-Object parameter, which is your Database. You can then Query the information you need, save them and then create the new Database-tables. After that, you can insert your saved data back into the Database.
Can't you cope with thus in your DB design? Have a user favourites table that holds id's. So long as these id's don't change upgrade won't affect it surely?
One possible solution is backing up part or all of your database to restore at a later time. I found this guide quite handy http://www.screaming-penguin.com/node/7749
Alternatively, you may save their favorites as a SharedPreferences. http://developer.android.com/reference/android/content/SharedPreferences.html for more information on that.