26

I have an application which has some static variables. These variables are stored in an independent Class named DataContext. These variables are initialized from raw files at the application start (a method named DataContext.initConstant() is called in the onCreate() of MyApplication which extends Application).

(EDIT : the initConstant method use an AsyncTask to load this data from files).

When my application comes to the background for a certain time or when my application used to much memory, these static variables become null.

  1. How can it be prevented?

  2. If not what should I do with my static variables?

    I have other data which are stored in static variables to be used across different activities, but I clear them or pass them to null in the onLowMemory() of MyApplication.

  3. What is the best way to keep some data accessible between activities if these data are too big to be serialized in an Intent, a database can't be used (for whatever reason), and can't be stored in files through serialization either?

Community
  • 1
  • 1
MathieuC
  • 271
  • 1
  • 3
  • 6

7 Answers7

5
  1. You can't. Android needs to free up memory from time to time. Imagine if all applications had a ton of static data that is supposed to be resident forever - how would you fit that in memory? It's a mobile phone. It doesn't have virtual memory.

  2. (and 3): Anything that is intended to be persistent needs to be stored, either via SharedPreferences, a Sqlite database, or a file.

EboMike
  • 76,846
  • 14
  • 164
  • 167
  • Ok thanks, but I can't change the way my app is working now. But I will certainly change it if I could. – MathieuC Jan 26 '11 at 09:35
5

Most likely the issue is that your application is being killed while it is in the background, and then recreated when you come back to it. Check out the Activity Lifecycle documentation on when this might occur for a single activity. You need to make sure that you move anything stored in memory to more permanent storage at the correct point in time to avoid losing that information if the app gets killed.

I'm not sure what exactly you are storing, but it sounds like using Shared Preferences might work well. This page on Data Storage explains a number of different ways of more permanently storing data, including Shared Preferences.

Cheryl Simon
  • 46,552
  • 15
  • 93
  • 82
  • 2
    The application is not killed because if so my static variable would be recreated because if the application is destroyed, then when it will be recreated the onCreate() method of MyApplication would be called. – MathieuC Jan 25 '11 at 18:33
2

I assume this is a data cache problem.

Storing data in static class is not guaranteed to work when user swap apps often. Android system will reclaim any background activity when memory is low. Static class is definitely among this category.

The proper way to do it is to use sharedPreference to persist cache data.

You can create your own getter and setter of the data you want and wrap it around sharedPreference object. When you access using getter, you should always check if the value is empty or expired. You can store an update_time when using setter.

For activity specific data, you can just use getPreference(permission), if you want to share data across activities and other applications components, you can use getSharedPreference(name, permission).

Normally, the permission will be MODE_PRIVATE such that the data can only be accessed within your application.

You should group data and store in difference sharedPreference object. This is good practice because when you want to invalidate that group of data, it is just a matter of one liner.

editor.clear(); editor.commit()

If you want to cache complex object, you should serialize it. I prefer JSON format. So you need some conversion mechanism in place. To do this, I will create my data object class extending JSONable class. JSONable class will have toJSON() method and readFromJSON(). This is convenient when restore and serialize data.

coderek
  • 1,860
  • 14
  • 20
2

If you weren't using raw files, I'd advise initializing when the class is loaded.

For instance,

public static Map<?,?> myStaticMap = new HashMap<?,?>();
static { //fill myStaticMap }

You do have some bigger concerns to worry about if you are loading files that way. For instance, what about I/O errors, or latency issues? You will get warnings in gingerbread (if you enable them) for doing I/O in your main thread. Perhaps you should have an object to retrieve these values instead of a class with static fields. (perhaps with a static cache, although you should synchronize on it before checking/changing it)

sargas
  • 1,113
  • 12
  • 20
  • Don't worry my loading is not in the main thread (I use an AsyncTask to do the work in my initConstant method. – MathieuC Jan 25 '11 at 18:34
  • 1
    If DataContext.initConstant() is called in an AsyncTask, then when your application is destroyed and restarted by the system, there will be a time between your Activity is created and expect DataContext to be populated and the time when it is actually populated. It's possibly the reason why you found it to be null - it hasn't been recreated yet, but some of your Activities expect it to be fully initialized by the time they run. – Kai Jul 16 '13 at 04:03
1

In your onResume() method you could query the static data to see if it is present and if not, load it back in again.

cjk
  • 45,739
  • 9
  • 81
  • 112
1

I store a User object and a Client object in my static scope. I have noticed from time to time the reference becomes null. So now in my getters I check to see if this value is null and if so I restart the app.

Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                context.startActivity(i);

I could have also chosen to reload the Client because I store the Access Token in prefs however I do so much initialization that I decided restarting the app would the best idea.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • Thanks, but that mean if the user has a very old device the application could restart very often, no ? – MathieuC Jan 26 '11 at 09:39
  • Hmm not exactly. I actually put the static variables in the Application class of my android app. These vars almost never become null unless the whole app is removed. I noticed the only time these become null is when someone uses task killer to stop the app but the current activity is still live. So that's why I think this is such a rare occasion that I will just restart the app. – Amir Raminfar Jan 26 '11 at 14:06
0

Instead of using the static variable u can use the shared preference for storing the value.

Note: for shared preference also you should not give heavy load.

I have solved this problem by having the super class with getter and setter function for storing and retrieving shared preference variable.

All class in my application extended the super class instead of activity.

Rooban Ponraj A
  • 281
  • 4
  • 20