I want to keep some objects in memory for operations in all the activities of my app and I also want to store those objects when the app closes. Which is the most efficient way of doing this ? Some possibilities that I can think of are:
1) Keeping local copies of objects in all the activities, serialize them and pass them through intent.
2) Keep local copies of objects in all the activities, serialize them and do file read and write on activity resume and pause respectively.
3) Make them static variables but I don't know when to do the file read/write operations in that case? This approach may leak memory.
4) Use Application object and define my objects as variables in that object. Since it has a definite life cycle like activity, I can do read/write accordingly.
I recommend your approach number 2. The reason is that there is no such thing as "the app closes". Android tries to keep it in memory until the memory is needed for other purposes. The process of your app is then simply killed, you don't get any callbacks called.
Singletons or the Application object can be used to cache the objects if you are careful to load and store them as necessary. However, this also means, that the memory used for them is only reclaimed if the app process terminates.
It depends on your data. All approaches are good in some cases.
I think you have 2 options:
keep data in sqlite. It is easier then files and faster. When activity starts request required data from db and show it. (use files if you really want)
create a singletone class to store data. Data will be loaded in memory and you can access it very fast. When data changes save it to sqlite or file. google "share data between activities"
Related
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.
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/
I am new to android development and I see that there are different components (activities, services, etc.) where each component has a different life cycle.
I am encountering a situation where I have an object that should be accessed by different components. Namely, I have a list of objects that changes dynamically, and that list should be accessed by:
An activity that displays the list in a ListView
A broadcast receiver, that responds to alarm events scheduled in the AlarmManager.
The broadcast receiver may kick in hours after the activity was used. At this time, the activity may or may not be still alive in memory.
Is there anywhere I can put the list so it will be accessible to all app parts? My idea was to serialize the objects I need to share, write them to shared preferences and then recreate them whenever needed. I'm not sure it's a good idea, and even if it is - how would I design it? when would writing to shared preferences (or somewhere else) occur? when would reading occur (it would be preferable to read the object from memory when possible)?
You can put it in SharedPreferences if it a compatible data type, or serialize the list to a file in the internal or external storage (see saving files, you probably want internal storage for your situation).
You can read the list in the onResume() method of the Activity or the onReceive() method of the receiver. Writing will occur whenever a new element needs to be added to the list, you will deserialize the list, add the element and re-serialize it. You may need to place the reading and writing in a synchronized block or method to prevent simultaneous access.
If the list may be added to outside of the Activity when the Activity is resumed you may need to provide a broadcast receiver or other mechanism for the Activity to be alterted and reload the list.
As Gabe pointed out, you could store it in a static variable somewhere, but the way you described the situation serializing sounds like a better option. Otherwise the list is gone if your process is terminated by the Android system.
As kcoppock pointed out, you could use an SQLite database to store the data, but this sounds like overkill from what you described. You will be in for some additional coding without much benefit.
What you are looking for is the Android Shared Preferences. You can access Sharepreferences using getApplicationContext() from an Activity or a Service.
Hope this helps
If you don't want it permanently stored, put it in a static variable somewhere (anywhere they both agree to- a separate class would be a good idea). Then you can access the list unless Android kicks the class out of memory- which it should only do it its terminating the app due to lack of memory, in which case it doesn't matter much anyway.
If you do want it permanently stored, the filesystem is the best way. You'll need to synchronize access to it of course.
I have a database from where i need to extract quite a lot of data.
Now i get that data when required, i.e. I have made a class that handles database interactions and whenever an activity requires data it will call that class for the data. So at a time an Activity only has the bare minimum amount of data in memory (i.e. the data that it is using). But everytime i change an activity i have to perform database access to fetch data for the new activity.
Method 2
As opposed to this i have this other alternative, in which i make an application object and then perform database access in the beginning and then store all the data that i would require (in all the activities) in the application object. Whenever i need the data, i refer to the application object. The downside of this that i will be holding too much extra data that i am not using at a given instant.
Which of the above 2 approaches is better?
Thank you in advance.
It depends on your requirements and their priorities. If the time required for solution 2 is too long for you to accept then optimize (e.g. by using method 2, but in general I would advise against storing potentially all of your database in memory ... assuming the amount of memory will suffice).
Did you try solution 1. If the problem is only to read the data from database, it should not take too long to load the data for one activity. If complex calculations are involved you might be pressed to optimize. But don't optimize just in case!
I prefer the first approach because making a call to database is not costly until and unless it is being accessed by multiple applications.
Ddms tells that, when I recall my class called in the past, it performs an onCreate() instead of onResume() that I expected...
I noticed that values that I stored in variables of my class in this case are lost and are null.
I presume that Android decide to do so to free memory resources (isn't it?).
I know that I could use Sharedpreferences to store data in a persistent way and then retrieve... But this is a really dirty way, in my opinion.
So, my question: how to have variables' values preserved also after an onDestroy() (I think?) that Android decided automatically?
Android will terminate your process at any time when you have no visible activities. For example, the user might go into Settings and terminate your app.
Static data members (my interpretation of your "variables of my class" description) are only meant to be caches, at best. They are no substitute for a persistent data model, whether you use a database, an XML file, a JSON file, or whatever.
So, if you want "variables' values preserved", save them someplace persistent.
You might find this page on data storage helpful. If your data is primitive, SharedPreferences are the recommended route. (Why do you think they are dirty?) If you need to store an object, you can use internal storage, as documented on that page.
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
If you don't like SharedPreferences, then you might want to look into Content Providers Even though Content Providers share data across applications, they also provide functionality for you to store persistent data in SQLlite and files that are available only to your app. In this case data stored in this fashion will be available even after closing and restarting your app.
You can save dynamic state by passing name:value pairs or serializable objects using the Android Architecture and the methods onSaveInstanceState and onRetainNonConfigurationState. You can persist state as explained in the other answers by writing to prefs and doing database writes.
I've been using custom Application class to store data over application life line.
How to declare global variables in Android?