1

This is my first time using SharedPreferences in my Android app. Since I will be using the SharedPreferences over and over again, I have created a utility class called SharedPreferencesUtil which contains a lot of static methods which allow me to access and modify the values. For example:

   /**
     * This method is used to add an event that the user
     * is looking forward to. We use the objectId of a ParseObject
     * because every object has a unique ID which helps to identify the 
     * event.
     * @param objectId The id of the ParseObject that represents the event
     */
    public static void addEventId(String objectId){
        assert context != null;
        prefs = context.getSharedPreferences(Fields.SHARED_PREFS_FILE, 0);
        // Get a reference to the already existing set of objectIds (events)
        Set<String> myEvents = prefs.getStringSet(Fields.MY_EVENTS, new HashSet<String>());
        myEvents.add(objectId);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putStringSet(Fields.MY_EVENTS, myEvents);
        editor.commit();
    }  

I have a few of questions:
1. Is it a good decision to have a utility class SharedPreferencesUtil ?
2. Is the use of assert proper?
3. Is that how I will add a String to the set?

An SO User
  • 24,612
  • 35
  • 133
  • 221

2 Answers2

1

You can check out how to use SharedPreferences properly here and check another example on the Android docs.

EDIT: As to your design question, it really shouldn't matter to have a static class or not.

Your SharedPreferences are shared throughout the app, and although you can create multiple SharedPreferences objects, they will essentially store and save to the same part of your app as if you just used one object.

Community
  • 1
  • 1
rageandqq
  • 2,221
  • 18
  • 24
  • Oh not that! I know how to use the methods of `SharedPrefernces`. I want to know if it is a good design decision to have those static methods – An SO User Jul 07 '14 at 17:54
  • It really shouldn't make a difference using a static utility class or not. – rageandqq Jul 07 '14 at 17:57
1

In general I think utility classes like this are fine. A few recommendations I'd have are:

  1. Initialize your Context in a subclass of Application (in Application.onCreate()) and store a reference to that in your utility class. You don't have to worry about a memory leak if you ensure you only use the application context instead of an Activity context, and since SharedPreferences doesn't use any theme attributes, there's no need to use an Activity context anyway.

  2. Check and throw an exception warning that the class hasn't been initialized yet if you try to use it without initialization. This way you don't need to worry about checking for a null context. I'll show an example below.


public final class Preferences {
    private static Context sContext;

    private Preferences() {
        throw new AssertionError("Utility class; do not instantiate.");
    }

    /**
     * Used to initialize a context for this utility class. Recommended
     * use is to initialize this in a subclass of Application in onCreate()
     *
     * @param context a context for resolving SharedPreferences; this
     *                will be weakened to use the Application context
     */
    public static void initialize(Context context) {
        sContext = context.getApplicationContext();
    }

    private static void ensureContext() {
        if (sContext == null) {
            throw new IllegalStateException("Must call initialize(Context) before using methods in this class.");
        }
    }

    private static SharedPreferences getPreferences() {
        ensureContext();
        return sContext.getSharedPreferences(SHARED_PREFS_FILE, 0);
    }

    private static SharedPreferences.Editor getEditor() {
        return getPreferences().edit();
    }

    public static void addEventId(String eventId) {
        final Set<String> events = getPreferences().getStringSet(MY_EVENTS, new HashSet<String>());

        if (events.add(eventId)) {
            // Only update the set if it was modified
            getEditor().putStringSet(MY_EVENTS, events).apply();
        }
    }

    public static Set<String> getEventIds() {
        return getPreferences().getStringSet(MY_EVENTS, new HashSet<String>());
    }
}

Basically, this avoids you having to always have a Context on hand to use SharedPreferences. Instead, it always retains a reference to the application context (provided you initialize it in Application.onCreate()).

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • Point 1 is what I am doing currently. Point 2 is what I was planning to do but assertion seemed simpler – An SO User Jul 07 '14 at 18:57
  • 1
    Assertions aren't actually enabled by default, and shouldn't be left in when you release your app; besides, it's better to throw a specific exception stating the proper resolution (call initialize()). – Kevin Coppock Jul 07 '14 at 19:01