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.
Related
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.
I am using axios for API calls, and Async storage for storing some details like user profile and all. But Async storage seems very slow.
My apps' key functionality needs internet to work, but lot of screens would have content which doesn't update in realtime or always. How do I save all that info in local so whenever new session of the app is launched, the screens show fully loaded instead of querying data from API and showing a loader, the info update can happen in the background. Like how all the major apps work is by not loading already loaded content but somehow saving it on the device itself, but at the same time allowing for updating if new info comes in.
Some sort of DB in the app to store all info would work? if yes, what's the best to go with Redux, Axios implementation that is fast and not as slow as Async Storage?
Async storage should work fine. To implement this, you will need to make sure to use the API data only on the first app start, and not subsequent starts. Then add an updater function that checks for updates. Here's a rough implementation.
When App loads, try to get your data from the local storage. If it's the first start, there's nothing in the storage, so fetch the data from API.
Once data comes back. Save it to the local storage for next app start. Display the data.
If the data exists in local storage (subsequent starts), you will need to send a API call to fetch the latest data. Once the data comes back, put it in the local storage. Make sure this is not a blocking call. It's up to you if you want to update the current data on screen.
I have worked on several projects using the redux-persist library. In short, what it does is cache the information you handle with redux, without having to worry about saving information with Async storage.
If you really don't want to use Async storage and you already use Redux, I think it's the perfect option. I have been with this library for about 2 years and so far I have not had any problems.
For more information visit:
https://github.com/rt2zz/redux-persist
So the app is for a Parrot Rescue. It will contain profiles for each of the birds that we currently have for adoption. So a picture of the bird, and then basic info about the bird. It needs to be regularly updated as the birds are adopted out and new ones come in. What route should I go? My main concern is that I want it to be relatively easy to update so that some of the less technically inclined could use it, as I won't always be available to help them.
Instead of loading a new version of the application every time, you should implement a database on a parrot information server. Then the application (the client) will ask the server to receive parrot information.
Just implement a mySQL database and a PHP page that returns the information in JSON format. Then through the application you will make a request to the server using the volley library or okHTTP and enter the information into a list.
As there are also pictures, use the glide library to download the images.
Also remember to upload small images to the server.
This way the app is always up to date
The easiest way is to update the app on the play store with the newest db, and let auto-update update the app with the new db.
Next easiest is to have a nightly (or whatever frequency) service download a new db and replace the old one from your servers
If you want it to be as easy as possible to update for everyone I would recommend a little app that has two main activities. One for displaying the entries of the database (and maybe also giving the ability to delete the entry) and another with a template to fill with all information and the image.
Then like Raffaele D'Arco explained use a little server. You could also delay the updates to be in a 5 minute routine or the like so that you put as little stress as possible on the server.
There are multiple good ways to update the interface without updating the app constantly.
Use a database which the app will download after a fixed amount of time which will be located on the server.
Secondly, if you have a website you can convert the web pages to XML or JSON or something like that and can update the app UI as per the data downloaded from the website.
I would recommend the second option as it is quite easy than the first one...
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.
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.