Static application scope datastore VS passing data per bundles - android

I wonder about following, maybe someone can clear that up for me:
I am having an application which loads some json feeds initially on application start.
This data is needed in each fragment, and the standard way for me would be to retrieve it in the MainActivity and to pass it in bundles to my fragments.
Downside: Serialisation, complicated Datasync, lots of bundling and unbundling code.
What about just putting the data in some global, static DataSource class and accessing it from the fragments/activities? Would be super simple - however, it seems to have a drawback:
When fragments are resumed after the app stayed in the background for a while, it seems that all global static data is lost.
How would you handle such a usecase? Is there a way to persist and reload static data without having to map everything and store it into a DB?

I am having an application which loads some json feeds initially on application start.
Nobody has universal, perpetual connectivity. Hence, you need a persistence strategy to deal with the cases where the user wants to use your app but is unable to connect to the server, for whatever reason.
When fragments are resumed after the app stayed in the background for a while, it seems that all global static data is lost.
That is because your process was terminated, and your JSON is not part of your saved instance state. Large model data, like your JSON, usually is not something you want as part of your saved instance state anyway.
How would you handle such a usecase?
Use a file or database on internal storage as a backing store. Static data members are only a cache for such a persistent store, nothing more.
Is there a way to persist and reload static data without having to map everything and store it into a DB?
You already have the JSON. Write it to a file, if nothing else.
As noted earlier in my answer, you need to have a plan in mind for dealing with a lack of connectivity or other reasons why these feeds cannot be retrieved. That should tie into your persistence strategy. The Internet updates your persistent store (and, along the way, updates any in-memory caches).

Related

Are there any concerns using an object to store data retrieved from a server?

Will the Object be around for as long as the app is in the background? Does anyone know when a Kotlin Object get removed from memory and reset in Android? Should I just use a ViewModel instead?
When the app is in the background, you can't know what the system will do with it so you can't store in memory data you want to persist.
You have different solutions:
If it's data from a server, you can make the call again if the app has been destroyed between the moment the user put it in the background and the app is brought back.
You can store the data locally.
In the second case you have 3 solutions:
Persist the data into a SQL database, using a solution like Room for instance. This is usually the way to do it.
Persist the data into the Shared Preferences. Used for light data, like settings or small preferences
Store them into a file (usually not a good approach)
A ViewModel is not a way to persist data. It will only persist data in memory. It is good to keep the data when the UI has been destroyed (app changes orientation, or Fragment put in the backstack for instance)
But if the app is killed (for any reason), so will be the ViewModel and everything it contains.
However following a MVP or MVVM (using ViewModel) pattern is a good way to build you app as it decouples the UI from the logic and helps with tests.

Persist object when changing Activity

I am currently facing a problem with persisting object state in an android app.
I have some kind of multi level master-detail flow.
For example, I have a list of Clients. Each Client has multiple Orders and each Order has multiple articles.
Until now I did the following:
When you click a Client in the MasterActivity I write the Client into the Bundle and open the DetailActivity.
In the DetailActivity I read the Client from the Bundle and display it.
This worked more or less fine most times, however it now happens, that an object is too big to be serialized (for example a Client with a lot of Orders).
Therefore I wanted to serialize only the ID of the Client and load it from the database inside the DetailActivity. Usually this approach works fine but I have one situation where it does not work:
The Articles are only saved, when you save the Order (their Master). So if you create a new Article for an Order and you don't save the Order, the Article isn't saved too.
That means, that I always need to have the full object, reloading it
from the database inside the DetailActivity means, that I loose all the unsaved changes. However, persisting it, using the Bundles could exceed the limit (500kB to 1MB).
So my question is, what is the preferred way to persist such data?
A nicer way is to create your own singleton class which points to data you want to transfer between activities.
I suggest DataManager singleton activity which has Article articleToPass
Make the setter set the articleToPass to point to what ever you want.
and the getter or reader, will read fetch the article and nullify the articleToPass.
manage your app data using this DataManager singleton (This dataManager singleton can be initialized either in the extending Application class or MainActivity).
Incase you must persist the object when app is destroyed and loading back:
Create from Article object a DB entry which contains all data you need (I see no reason why saving data you don't need here)
Dump all data to some file (Using Shared Prefs, key and values)
When entering the Details screen you want make a query to a sever of yours requesting all data you need by ID or such.
Convert all object you need to JSON (simply using GSON), and dump the JSON to a file, and load it when you need.
I think the resolutions above are enough :) hope i helped
You can subclass your own MyApp class from Application, specifying it in your manifest. This class is a singleton and is available all the time the android application is running like this (MyApp)getApplication().
So, in a field of this class you may keep some temporary data you need to keep between activities.
You have to check if this field is not null though because the OS can terminate your app anytime. In this case you will have to reload the data. You can keep some index of what data to be reloaded somewhere in the SharedPreferences.

How does android do GC?

Now I'm facing some problem in Android when memory is low or the application is killed by system.
Scenario 1:
I set some static members in a class, I found in some situation , it will be deleted by system when the application is still running.
My problem to this is : when does this kind of GC run?
Scenario 2:
If I switch to another large application and then switch back to my application ( named App_A). App_A sometimes will be recycled by system and restart the last activity when it be switched back.
But there are some application-wide data (like login info) I saved in a singleton.
My problem to this is : Dose the application-wide data saved in singleton will be deleted?
If so, is there a appropriate way to restore the data?
My effort is:
To Scenario 1, I will avoid to use static member directly.
To Scenario 2, I will save those data into file , after it be deleted, I pass Context to each public function to let each of them have the ability to restore the data. But I think it will be unfriendly when the function is used in some situation which need run quickly.
I can only answer about Scenario 2.
Android will try to keep recently used apps in memory, but if the user switches to another app and memory starts running low, the OS has the option to kill the recently used app to make more memory available to running applications.
I had the same problem, where I had some user-context data like username in a static singleton. This data would disappear when returning to the app after using a number of other apps.
The way I solved this problem was to use the activity's intent. Since the user data was retrieved at the beginning of the app, I would simply pass this data to subsequent activities in their intents. Because the OS stores the intent and uses it to recreate an activity not in memory, my data was no longer vulnerable to being garbage-collected.
Also consider other means of persisting data: Shared Preferences, file system, SQLite database. But never count on static data from previous execution being available at the start of an activity.
It is generally bad idea to use singleton to save some data.
Best practice is using any persistent storage - SQLite, Realm,JSON, or any file.
Easiest way is saving your login data for ex. in JSON - then in Application class parse it in onCreate method into POJO - then you can get it from any place of your app. And store to file when app is closing or on any change.
Anyway I suggest you to read Android guides about persistence, memory management and performance tips.

What's a safe way to store data in Android?

I've been using singletons to store data that is loaded when my application started. This data is used throughout the lifetime of my app, but doesn't need to be persisted for future launches. I've started hitting the issue though that my singletons are garbage collected and their data is wiped. Does the singleton pattern just not make any sense on Android? Using local storage or a local database seems like overkill, but I'm not sure what else to do to guarantee my data is safe for the lifetime of my app.
Thanks!
I've started hitting the issue though that my singletons are garbage collected and their data is wiped.
No, they are not. By definition, a singleton (static data member) cannot be garbage collected.
Most likely, what you are seeing is that your process is being terminated.
Does the singleton pattern just not make any sense on Android?
As a caching mechanism, it is fine.
I'm not sure what else to do to guarantee my data is safe for the lifetime of my app
A static data member is "safe for the lifetime" of your process. If you want data to survive process termination, you will need to store that data in a database, SharedPreferences, or some other sort of file.
Are you holding onto a reference to the singletons in the Application (http://developer.android.com/reference/android/app/Application.html) level of the app? That should keep them persistent for the most part (unless they're byte[] or something else huge).
The safest bet, however, is to assume that data will be garbage collected and structure your code with that assumption. If it's something from the web, define an asynchronous callback to load the data and then populate your views. If it's something local that is not user-generated, use the async to grab it from disk. If it's user generated, you might need to set up a database (which you can empty when you restart the app) to keep track of data.
But, if you haven't, tried keeping references to your singletons in the Application first. Brief intro here: http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

When Android relaunches the app after being killed in background

Of late I have been into an issue which has been really difficult to sort out.
I have an Activity A which has a view pager with fragments. I am loading data from server and feeding into the views. The data received from server is stored in a singleton class which can be accessed across the application. Now user moves to another activiy B which uses the server data through singleton class.
Now when user presses home and launches variety of application, my app gets killed in background. When I relaunch the application, OS try to load activity B again with its saved state(I am not doing anything in onSaveInstance), but the data in singleton class is already lost and app crashes. The thing is I cannot get the server data again in this activity. Should I save the entire data in onSaveInstance of this activity? Is it not encouraged to use singleton class to store all your data?
What is the ideal way to handle situation like this?Any help is appreciated.
How sensitive is the data? In Android is is not recommended to use a skeleton to move your data around(Passing it through intent? Static(please say no)). Ether way was commented you should probably store the data to main memory. Android provides a few options besides actually writing it to a file. Depending on how much data and its structure there are a few options.
ContentProvider & ContentResolver, Basic Overview. I would not recommend this unless you plan on making the data accessible to other applications.
SQLite. Good if you have preexisting sql knowledge or large amounts of data where a relation db is needed.
SharedPreferences. As its name implies is generally used for storing user presence data, but it can also be used to store any data. I would not recommended it where there is a lot or complex data is needed to be stored.
File. Good old java file classes, no explanation needed.
With our data I would recommend creating a DataStore managing class which handles the io to any of the above methods, so when referencing the data you simply pull from that class.
To avoid such situations, you should relate to these:
App crashes when restoring from background after a long time
http://www.developerphil.com/dont-store-data-in-the-application-object/

Categories

Resources