3

I have an android app, where there are couple of activities. Each of the activities download an xml/json feed, parse it and push that to a singleton usually as an arraylist.

However after going through various activities, It seems the singleton is dying and most of the earlier downloaded array lists are now empty. Why is it so? Isn't singleton a recommended practice for sharing data across activities?

Azlam
  • 2,052
  • 3
  • 24
  • 28
  • Can you post some code of your Singleton Class? I'm using a similar solution without any problems. – mouser58907 May 16 '12 at 16:59
  • 2
    If you want to keep a global variable across activities then keep that in Application. Extend a class from Application and add that in your AnddroidManifest file. – Tarun May 16 '12 at 17:00
  • Tarun's suggestion is a good and common way of doing this on Android, but there's no reason your singleton shouldn't work as well. I'm with mouser, if you could share your code we'll take a look. – Kevin Coppock May 16 '12 at 17:02
  • Thanks guys, I am guessing the singleton is getting recycled, as the old activity which actually created the singleton dies and if the new activities doesnt have any reference to the singleton – Azlam May 16 '12 at 17:06
  • @kcoppock Suppose you have initialized singleton class in Activity1. How will you keep the singleton class member variables values if the activity 1 is killed.? – Tarun May 16 '12 at 17:07
  • Here is a related question http://stackoverflow.com/questions/3826905/singletons-vs-application-context-in-android – mouser58907 May 16 '12 at 17:09
  • Would synchronization help ?http://stackoverflow.com/questions/9502858/what-are-the-chances-a-singletons-instance-variable-becomes-null-in-an-android – Azlam May 16 '12 at 17:11
  • @Tarun: Maybe I'm misunderstanding the question, but that's the point of the singleton model. There's at most one static instance that should remain alive as long as the application is alive. – Kevin Coppock May 16 '12 at 17:28
  • @kcoppock That's where Application context is used as the Application context is designed to have only one instance. – Tarun May 16 '12 at 17:37
  • @TarunMaheshwari: Yes, the Application class uses the singleton pattern as well, but he should also be able to implement his own. – Kevin Coppock May 16 '12 at 17:39

3 Answers3

3

Adding my comment as an answer

If you want to keep a global variable across activities then keep that in Application. Extend a class from Application and add that in your AnddroidManifest file.

From the Android API FAQ shared by @rekaszeru

Singleton class

You can take advantage of the fact that your application components run in the same process through the use of a singleton. This is a class that is designed to have only one instance. It has a static method with a name such as getInstance() that returns the instance; the first time this method is called, it creates the global instance. Because all callers get the same instance, they can use this as a point of interaction. For example activity A may retrieve the instance and call setValue(3); later activity B may retrieve the instance and call getValue() to retrieve the last set value.

Tarun
  • 13,727
  • 8
  • 42
  • 57
2

Please see this thread of Android API FAQ, here you will surely find the most appropriate solution for your problem (whether you need a short-living or a long-life data).

Singletons are used for short life-cycle objects.

Edit: Please keep in mind, that for extensive amount of data it is always a better idea to use databases / structurated local files (though the latter are resource-consuming to read/write). And if you are working with very complex object, choosing SharedPreferences might cause some headache too.

A sample of storing / loading a list from SharedPreferences:

// the name with which to store the shared preference
public static final String PERSON_LIST = "my.personlist";

// a sample data structure that will be stored
public static final class Person
{
    private String name;
    private int age;

    public String toString() 
    {
        return name + "|" + age;
    }

    // splits the passed String parameter, and retrieves the members
    public static Person loadPersonFromString(final String personString)
    {
        final Person p = new Person();
        final String[] data = personString.split("|");
        p.name = data[0];
        p.age = Integer.parseInt(data[1]);
        return p;
    }
}

/**
 * Saves the current list of Persons in SharedPreferences 
 * @param persons: the list to save
 */
public void savePersonList(final ArrayList<Person> persons) 
{
    final SharedPreferences prefs = PreferenceManager.
        getDefaultSharedPreferences(getApplicationContext());
    final Editor editor = prefs.edit();
    final StringBuilder builder = new StringBuilder();
    for (final Person person : persons)
    {
        if (builder.length() > 0)
            builder.append("-Person-");
        builder.append(person.toString());
    }
    editor.putString(PERSON_LIST, builder.toString());
    editor.commit();
}

/**
 * Loads the list of Persons from SharedPreferences
 * @return the loaded list
 */
public ArrayList<Person> loadPersonList()
{
    final SharedPreferences prefs = PreferenceManager.
        getDefaultSharedPreferences(getApplicationContext());
    final ArrayList<Person> persons = new ArrayList<Menu.Person>();
    final String[] array = prefs.getString(PERSON_LIST, "").split("-Person-");
    for (final String personString : array) 
    {
        if (personString.length() > 0)
            persons.add(Person.loadPersonFromString(personString));
    }
    return persons;
}
rekaszeru
  • 19,130
  • 7
  • 59
  • 73
  • so we should check if the objects do exist and repopulate the singleton? – Azlam May 16 '12 at 17:07
  • actually I would go for a persistent storage, and if you don't want to bother with database design and dml, then the best would be using application preferences: `SharedPreferences`. With a custom reversable (parsable) `toString()` override you can store there all the important lists you need. `SharedPreferences` are always kept, easy to access, and will provide always the actual (latest) value, no matter from which activity you retrieve them. Above that, you can register listeners to notify you when something changes. – rekaszeru May 16 '12 at 17:13
  • do you have an example or if you can post a snippet of the code of how to implement reversable parsable? – Tarun May 16 '12 at 17:14
  • please see my update for a quick sample and some explanation. Note, that this is just the concept, there are more efficient ways to do such String-manipulation; the sample above is just for a better understanding. – rekaszeru May 16 '12 at 17:46
1

You might initialize through an Application class. This class is present across all activities. You must declare it in the Manifest file and has a life-cycle similar to an Activity.

Documentation here: Application

Hope it helps.

JQcorreia

JQCorreia
  • 727
  • 6
  • 15