About Single Sources of Truth Google document said:
Using this model, the database serves as the single source of truth, and other parts of the app access it using our UserRepository. Regardless of whether you use a disk cache, we recommend that your repository designate a data source as the single source of truth for the rest of your app
https://developer.android.com/jetpack/guide?gclid=CjwKCAjwo4mIBhBsEiwAKgzXOH1Pq--Ws1PLzUiSP4RmDE6ByKfEi6mdXu5g86btqveIdJvvrgYuxBoCz8wQAvD_BwE&gclsrc=aw.ds#connect-viewmodel-repository
According to the document I save all data when I fected data from remote server and I only get data from room When I need to use in acitivty(In fact I collect flow which is defined in viewmodel).
It seems so good! It avoids the different data sources mix up together! But actually I found some strange question gradually:
In my App, I have a list that the server may change it(Because we have data manager website that admin can update or delete data). So in order to get the newest list data from server, I must clear all data stored in room and fect data again from remote server. This operation seems redundant: "why could I get data directly from remote server", I mean, I only get data from remote source is also a single sources truth. And also it cause a promble: my app will flash a moment because clear data make list empty and fect data from server make list full!
The most important thing is that it seems like the local data is not necessary because I must stay the newest list from remote server.
Some people may say that save data into room can make us app available offlice. I agree that, But in this place, my item of list is represent a image url, and after click the item, the app will jump to a new activity and display a ImageView base on the url we get from the list. If app offlice, the ImageView couldn't load the url also.
I am so confused I couldn't load all image url(use base64-url to avoid load invalid) in a moment also, because the data is so much. And if I say I need a search function in this list and I need load so much unbelievable data into my room, It seems so unreal and event fantasy!
In brief:
Room is a nessary? Couldnt just fect data from remote?
If room is nessary, how to solve problem I met, do my incorrect useage cause the problem?
Hi #psycongroo as I Understood your problem, and I want to share my experience:
You can handle any error with loading URL with placeholder I mean if you got an error with no Internet connection user will see placeholder, but in general libs like Picasso or Glide can cache images when it`s load one time, so the user will see the Image.
The question about why we need to use room instead of fetch data from remote directly. So from your question I don`t understand why you need to drop your local changes even they are completely new, user can have a low internet connection so he will see an empty list instead of previous data with for example progress indicator. And also if the user doesn't have the internet at all you can show some dialog to explain what the problem but old data is still present. If you are using, for example, RecyclerView you can update data with Paging 3 from google, and they update the only necessary items from your list.
P.S. let me know if that help, or you have another question.
Related
I am currently running into some issues regarding the realm database and I don't know what the best practices are to tackle this problem.
So I have setup an app which communicates to a server and gets Post Objects through Retrofit stored into my Realm. This post feed is a core part of my app and I want to keep things locally to stay attractive while being offline. The thing is that I cannot store the entire feed list locally as this would be a massive chunk of memory. But I want to make sure that the User gets this content while scrolling through a recycler-view.
The recycler-view currently only shows local Posts and updates them if refresh is forced. I want to implement a load on scroll mecanism that loads Post objects into it while scrolling but this scroll objects should not be stored locally when the app closes.
I thought of creating an additionally in-memory Realm but there is another problem: A Post Object contains a ForeignKey to a UserObject. When I download this dynamic PostObjects and a UserObject changed over this time on the server I want to be able to reflect this changes to every other User on the local persisten Realm too. (To avoid having 2 different UserObjects for the same User)
My best idea i came up so far is to have a
Boolean field on the PostObjects set to true or false to indicate temporary state or not. After the applications closes I would drop all the temporary entries. Is this a viable solution or do I miss anything? I hope you understand my problem and can help.
Edit: My Realm Database contains two relevant objects:
User
Has a name (primarykey), id (global from server), imageUrls etc..
Post
Has a User who created it, again an id and its data (text, date, images...)
Edit2 : What I really need is a type of in-memory Realm that allows me on start up to clone another realm that is used to have data in case of no connectivity. Before the in-memory realm gets deleted I would then override the offline realm with the 5-10 last post entries of the temporary realm. Is such a thing possible?
Actually, I followed this YouTube tutorial and got an idea of delivering articles from a WordPress blog using the JSON API.
Here is the GITHUB link.
The above tutorial has a good example, but it only shows data from database only when there is no internet connection available. But I want the following:
Fetch data when the app is first started.
Store the data in the database
Set the adapter and show the data in the recyclerview
When the app is loaded for the second time check if internet is available and then check for new data, download if available, and then save the data into database and show the data in the recycler view.
Now, I've developed most of the logic for it, but the tutorial has used some advanced OOPs principles of JAVA which I am unable to fully comprehend.
Can anyone please help me and tell me how I can change the given code and display the data from database even if internet is available or not?
on MainActivity, line 91
if (getNetworkAvailability()) {
getFeed();
} else {
getFeedFromDatabase();
}
Above code will check network, and if network available, getFeed() which load feed from internet will be called. Just remove that case. I mean, remove above code, just keep the line
getFeedFromDatabase();
There is nothing complex, by the way. The idea is that you define your own interface which describe how to save data and implement it for database and for communication with Rest Api (Retrofit). There may be some differences between format of stored data (one form in database and the other on a server), so you have to convert it to format of your app.
For that you create another interface (see Repository pattern), which is also implemented by you db and web stuff.
When your have implementations for both sources you can choose which one to use.
Context
I have a news activity which contains a ListView . Each item in the list contains some text and one image. Now every time the user opens the activity, the application makes a request to the server for getting data. Unfortunately if the user doesn't have an active internet connection, I simply put a Toast saying "Please check your internet connection"
Requirements
I would like to show news article from the last session if the user doesn't have an active internet connection. I define session as the time when user launches the activity and exits it by pressing back button.
Libraries used
I am using Retrofit Library for making Http Requests and Picasso for loading images.
What I have tried so far
While exploring Retrofit, I found out that retrofit by default caches the response for some time. So without any internet connection also I am able to get the data. In Picasso also, I found that we can save the image to any location on the device.
How to go for its Implementation ?
Since it will be a big change in my application, I wanted to know what is the best way to enable offline reading using the above two libraries? How do other applications manage to do so? Also if I can get some references or some blogs regarding this implementation, then it would be great.
Use the internal storage of the application.
Parse the image to a byteArray and the text to a single String so you can easily convert this also to a byteArray.
Name the files so you can easily retrieve them and link them back together.
You can storage the last updated data on local, with SharedPreferences or json file.
Instead of show toast, you can load the last updated data from local.
Picasso is a good choice for images, it saves images locally and reuse it automatically later.
For your items, I suggest to use a small local DataBase : in Android, we use SQLiteDataBase. here is a small tutorial : http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/
So, I suggest you this pattern
user opens activity
system retrieves data from database
in parallel, system starts to download the new items.
When new items have been downloaded, you should notice user like 9gag or Facebook apps do.
I'm working on a movie app, when the user first open the app I would fetch the most current popular movie data and populate it in my ListView. The initial fetch provide a list of movies, but only provide the basic information to fill a ListView (id, name, rating, release data, poster image url). To get the remaining data (run time, tagline, description, movie website, etc), I would have to fetch from /movies/{id} endpoint for each of the movies. Also, for a list of trailer, I would need to fetch from /movies/{id}/videos. Currently I'm fetching the movie detail data when they select the movie on the list using AsyncTask and then setting the Views with the data on the initial detail loading. I'm caching the data in a Content Provider and SQLite.
My questions are:
How do I prefetch the data after getting the initial list of movie
from the first fetch? I'm currently using an AsyncTask for the
initial fetch, do I just start a list of AsyncTask in the middle of
the initial task?
Should I even be using AsyncTask for this situation or are there
better alternatives? It seems like a SyncAdapter is a good idea for
the initial fetch, but not sure what is best to use for the
additional detail/trailer.
I just started working with Android a few weeks ago, so I don't know if I should even be doing things this way or if there are better solutions. Currently everything works, but I'm not sure if I'm going down the right path. I did read this, but wanted a more specific way on how to prefetch data.
This sounds like a good use-case for Volley.
[1] - After you have done the initial fetch you can create your Volley RequestQueue and fire off a bunch of Requests (String/JSON) that you can then parse / cache the result as you already do. Volley is asynchronous, so you do not need to worry about where you add them to the queue, but the callbacks are performed on the UI thread so make sure they are reasonable (they may cause animation jank)
[2] - See above.
I have an issue of saving app data internally on device, Well this go like below:
App is service based. We send a request a for particular home project and it will respond with an image of the project and a list of operations. And they want every link to be clickable and on click of that show more links with some text and images. Means lot of data to be handle.
The data which store internally should also get updates. So what could be the better option of saving it. Download files, download more files when update is required or go with SQLite database, which will update the existing db only.
Till now I am finding to create sqlite db as a better option, but still I want to know which could be the better option. I know this would create a memory issue, but this is what client want.