0

I have a list of custom objects ... these objects simple monitor a few of my websites for any new data that users may have added. I keep these objects in a static List<> that is a member of a final class .... I create a service to go through the list at a given interval and update as needed.

final public class MonitorHandler {
    public static List<MonitorSettings> monitorsSettings = new ArrayList<MonitorSettings>();

    ect....

}

everything works perfectly fine for some time ... no exceptions come up at all. But if I let the app run for a period of time .. like say over night the list is empty ... like the objects have been garbage collected or removed by android. Why is this?? don't static objects persist even after the app is closed or sent to backround?

fweigl
  • 21,278
  • 20
  • 114
  • 205

3 Answers3

1

Why is this?

Your process was terminated.

don't static objects persist even after the app is closed or sent to backround?

Only while the process is running. Your process can be terminated once it is no longer in the foreground. Whether that takes seconds or hours will depend upon what is going on with the device.

If you have data that you want to hang around, please store it in a persistent fashion, using a database, file, or SharedPreferences.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
1

Why is this?? don't static objects persist even after the app is closed or sent to backround?

No, if your app was actually closed by system, this might happen. You should log in your Service.onDestroy() to make sure this is really the cause, but it is not guaranted that onDestroy will actually be called.

So you should persist your data in some storage, preferable SharedPreferences or DB - sqlite.

marcinj
  • 48,511
  • 9
  • 79
  • 100
0

You haven't shown enough code to be certain, but it's very likely that you are not holding a reference to your data anywhere in your application except the static elements of the MonitorHandler class. The Dalvik VM will unload unreferenced classes from time to time, so the next time you access the class it is reloaded, the static initialisation is re-run, and you end up with a new, empty list.

The bottom line is that the only class that you can rely on not being unloaded during the execution of your Android application is the Application class itself.

If you want to retain data in your application the only approach that works is to maintain a reference to it from your Application class. In the case of your list the simplest way to do that is put it into your Application class directly. With more complex data you would probably want to create an instance of a separate class and hold a reference to it statically in your Application class. Here is an example showing two different ways to create the data, one statically, one lazily.

import android.app.Application;
import android.content.Context;
import com.example.DiskLruImageCache;

import java.util.ArrayList;
import java.util.List;

public class TestApp extends Application {

    static final public int CACHE_SIZE = 1024 * 1024 * 15;        // 15MB
    private static List<String> stringList = new ArrayList<String>();
    private static DiskLruImageCache imageCache = null;
    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = this;
    }

    public static List<String> getStringList() {
        return stringList;
    }

    static public DiskLruImageCache getImageCache() {
        if(imageCache == null) {
            synchronized(context) {
                if(imageCache == null)
                    imageCache = new DiskLruImageCache(context, "TestImages", CACHE_SIZE);
            }
        }
        return imageCache;
    }

}

Now in your Activities or Service you can simply call TestApp.getStringList() to get the list. Any changes to this will be preserved as long as the application is running.

Clyde
  • 7,389
  • 5
  • 31
  • 57
  • How about putting the Static List<> in the service itself .. would this be ok or bad practice? – Steve Jpbs Jan 23 '14 at 00:22
  • "The Dalvik VM will unload unreferenced classes from time to time" -- not according to the guy who probably wrote that portion of the VM: http://stackoverflow.com/questions/18840093/is-it-still-the-case-that-android-never-unloads-classes – CommonsWare Jan 23 '14 at 00:29
  • @SteveJpbs No, putting it in the service doesn't work - the service is not guaranteed to remain in memory either. I went through all these iterations in my own applications and using the Application class is the only thing that works. – Clyde Jan 23 '14 at 01:05
  • @CommonsWare Well, it is possible it doesn't *unload* classes, but it certainly appears to *reload* them if there are no live references to the class, which has the same effect. I have demonstrated this conclusively while tracking down a bug similar to that described by the OP. I don't know if there is any way of detecting when a class is unloaded, but I was able to log the re-execution of code in a static block in a class and that should only happen when the class is loaded. – Clyde Jan 23 '14 at 01:19
  • @Clyde: Most likely, that class was reloaded because the process had been terminated, and the class was loaded into a new process. – CommonsWare Jan 23 '14 at 11:41
  • I put the static list in the service is like you said it didn't work ... but one thing that is interesting is ... if the list becomes empty by removing items from the list the service is supposed to stop itself and restart if an item is added. For some strange reason the service stays running even though the list is empty ... and there is a process running as well .. seems strange to me the service should have stopped. – Steve Jpbs Jan 23 '14 at 20:41
  • @CommonsWare Nope, the process had not been terminated - the instance of the Application class was the same. – Clyde Jan 23 '14 at 22:19
  • @SteveJpbs Yes, it's quite normal for a service not to be cleaned up promptly. – Clyde Jan 23 '14 at 23:31
  • Well I took your advice Clyde and everything worked ... but not for long. Although the monitors stayed alive for a lot longer, putting them in the application class did not work either. Any other idea on why they would just vanish after 10 to 12 hours?? – Steve Jpbs Jan 26 '14 at 14:02
  • @SteveJpbs If the Application class instance has vanished, then your application has been killed. If you want data to persist between invocations of your app, you need to save it in permanent storage, e.g. a file or a database, then reload it when your Activity or Service is restarted. – Clyde Jan 27 '14 at 05:17