2
\$\begingroup\$

I just created a utility class for Android shared preferences. I want to know it is working well on other users device and useful for learners.

My code in gist

import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.util.Log;

import java.util.Map;
import java.util.Set;

/**
 * A utility class for android {@link SharedPreferences}.
 * All the creation of {@link SharedPreferences} use
 * MODE_PRIVATE constant of {@link Context} class.
 * Created on 2/4/2018
 *
 * @author Nyein Chan Aung
 * @version 1.0
 */

public final class SharedPrefUtils {

    private SharedPreferences sharedPref;
    private SharedPreferences.Editor editor;

    /**
     * A private constructor and initialize a {@link SharedPreferences} and
     * a {@link SharedPreferences.Editor}.
     *
     * @param context Context
     * @param name    {@link SharedPreferences}'s name
     */
    private SharedPrefUtils(Context context, String name) {
        sharedPref = context.getSharedPreferences(name, Context.MODE_PRIVATE);
        editor = sharedPref.edit();
    }

    /**
     * Create an instance of this class. Create a new instance whenever this
     * method is called.
     *
     * @param context Context
     * @param name    {@link SharedPreferences}'s name
     * @return SharedPrefUtils object
     */
    public static SharedPrefUtils init(@NonNull Context context, @NonNull String name) {
        return new SharedPrefUtils(context, name);
    }

    /**
     * This method return a {@link SharedPreferences} object with given
     * name. The main purpose of this method is to use all getX() method of
     * {@link SharedPreferences} class. You can also create a {@link SharedPreferences}
     * and use in normal way.
     *
     * @param context
     * @param name
     * @return {@link SharedPreferences}
     */
    public static SharedPreferences myPref(@NonNull Context context, @NonNull String name) {
        return context.getSharedPreferences(name, Context.MODE_PRIVATE);
    }

    /**
     * Put value to preferences depend on data type.
     *
     * @param k key
     * @param v value
     */
    public SharedPrefUtils put(String k, Object v) {
        if (v instanceof Boolean) {
            editor.putBoolean(k, (Boolean) v);
        } else if (v instanceof Integer) {
            editor.putInt(k, (Integer) v);
        } else if (v instanceof Integer) {
            editor.putInt(k, (Integer) v);
        } else if (v instanceof String) {
            editor.putString(k, (String) v);
        } else if (v instanceof Float) {
            editor.putFloat(k, (Float) v);
        } else if (v instanceof Long) {
            editor.putLong(k, (Long) v);
        } else try {
            editor.putStringSet(k, (Set<String>) v);
        } catch (ClassCastException e) {
            e.printStackTrace();
        }
        return this;
    }

    /**
     * Remove a preference value of given string key
     * if exist.
     *
     * @param key String, key to remoe
     * @return SharedPrefUtils
     */
    public SharedPrefUtils remove(String key) {
        editor.remove(key);
        return this;
    }

    /**
     * Commit Preferences changes and clear all data.
     *
     * @return boolean true on success, false on failure
     */
    public boolean finish() {
        if (sharedPref != null && editor != null) {
            boolean flag = editor.commit();
            sharedPref = null;
            editor = null;
            return flag;
        }
        return false;
    }

    /**
     * Show info of the preference with the name provided
     * in init method. The value will get from toString() method.
     */
    public void log() {
        Map<String, ?> map = sharedPref.getAll();
        for (Map.Entry<String, ?> entry : map.entrySet()) {
            Log.i("info - " + getClass().getName() + " : ", entry.getKey() + " : " + entry.getValue().toString());
        }
    }
}

Usage

////////////////////////////
To put value in preferences.
////////////////////////////
SharedPrefUtils.init(this, "my_pref")
                        .put("int_pref", 1203)
                        .put("float_pref", 1.203f)
                        .put("bool_pref", true)
                        .put("str_pref", "String Pref")
                        .put("long_pref", 100000000000099L)
                        .put("set_pref", setObject)
                        .finish();

////////////////////////////////////////////////////////////////////
To get value in preferences, use static method myPref(contex, name).
////////////////////////////////////////////////////////////////////
SharedPrefUtils.myPrfe(context, "my_pref").getFloat("float_pref", 0.0f);// assume context as a Context object.

/////////////////////////////////
To remove a value in preferences.
/////////////////////////////////
SharedPrefUtils.init(this, "my_pref").remove(keyToRemove).finish();
\$\endgroup\$
2
\$\begingroup\$

If I were a user of that utility, I'd prefer to know the accepted types without having to check out the actual code. So, I'd create put(String key, int value), put(String key, String value)...

In my projects, I usually have a similar class, overriding the get methods too (for removing the need to declare the default return value).

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Not that, not this either, not that, it must be a StringSet!

else try {
    editor.putStringSet(k, (Set<String>) v);
} catch (ClassCastException e) {
    e.printStackTrace();
}
return this;

Let's say you would try to put a Map in here, then this code would run. You would print a stacktrace (the end-user would not see this, and it's not the first place a programmer would look either), and you would silently fail. Don't do this. Throw an exception instead. Don't leave room for silent errors.

Finish!

public boolean finish() {
    if (sharedPref != null && editor != null) {
        boolean flag = editor.commit();
        sharedPref = null;
        editor = null;
        return flag;
    }
    return false;
}

Let's say that editor.commit(); would return false. Okay, you would return that status which is good. But you'd have no way of calling editor.commit() again as you are clearing the sharedPref and editor

With pure Android API

Let's imagine that you would not use your utility class and use the pure Android API, your usage is this:

SharedPrefUtils.init(this, "my_pref")
    .put("int_pref", 1203)
    .put("float_pref", 1.203f)
    .put("bool_pref", true)
    .put("str_pref", "String Pref")
    .put("long_pref", 100000000000099L)
    .put("set_pref", setObject)
    .finish();

The pure Android API usage would be this:

this.getSharedPreferences("my_pref", Context.MODE_PRIVATE).edit()
    .putInt("int_pref", 1203)
    .putFloat("float_pref", 1.203f)
    .putBoolean("bool_pref", true)
    .putString("str_pref", "String Pref")
    .putLong("long_pref", 100000000000099L)
    .putStringSet("set_pref", setObject)
    .commit();

Personally I would recommend other learners to use the pure Android API instead. Writing utility classes like this can be nice for your own learning, but think about if you provide any more functionality or if you in fact take functionality away.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.