Question

For my app, I need to save a simple SparseBooleanArray to memory and read it later. Is there any way to save it using SharedPreferences?

I considered using an SQLite database but it seemed overkill for something as simple as this. Some other answers I found on StackOverflow suggested using GSON for saving it as a String but I need to keep this app very light and fast in file size. Is there any way of achieving this without relying on a third party library and while maintaining good performance?

Was it helpful?

Solution

You can use the power of JSON to save in the shared preferences for any type of object

For example SparseIntArray Save items like Json string

public static void saveArrayPref(Context context, String prefKey, SparseIntArray intDict) {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = prefs.edit();
    JSONArray json = new JSONArray();
    StringBuffer data = new StringBuffer().append("[");
    for(int i = 0; i < intDict.size(); i++) {
        data.append("{")
                .append("\"key\": ")
                .append(intDict.keyAt(i)).append(",")
                .append("\"order\": ")
                .append(intDict.valueAt(i))
                .append("},");
        json.put(data);
    }
    data.append("]");
    editor.putString(prefKey, intDict.size() == 0 ? null : data.toString());
    editor.commit();
}

and read json string

public static SparseIntArray getArrayPref(Context context, String prefKey) {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    String json = prefs.getString(prefKey, null);
    SparseIntArray intDict = new SparseIntArray();
    if (json != null) {
        try {
            JSONArray jsonArray = new JSONArray(json);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.getJSONObject(i);
                intDict.put(item.getInt("key"), item.getInt("order"));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    return intDict;
}

and use like this:

    SparseIntArray myKeyList = new SparseIntArray(); 
    ...
    //write list
    saveArrayPref(getApplicationContext(),"MyList", myKeyList);
    ...
    //read list
    myKeyList = getArrayPref(getApplicationContext(), "MyList");

OTHER TIPS

Write the values separately, and keep a list of the names of the values you write:

    SparseBooleanArray array = //your array;
    SharedPreferences prefs = //your preferences

    //write
    SharedPreferences.Editor edit = prefs.edit();
    Set<String> keys = new HashSet<String>(array.size());
    for(int i = 0, z = array.size(); i < z; ++i) {
        int key = array.keyAt(i);
        keys.add(String.valueOf(key));
        edit.putBoolean("key_" + key, array.valueAt(i));
    }
    edit.putStringSet("keys", keys);
    edit.commit();

    //read
    Set<String> set = prefs.getStringSet("keys", null);
    if(set != null && !set.isEmpty()) {
        for (String key : set) {
            int k = Integer.parseInt(key);
            array.put(k, prefs.getBoolean("key_"+key, false));
        }
    }

String sets are supported since API 11. You could instead build a single csv string and split that rather than storing the set.

You can serialize the object to a byte array and then probably base64 the byte array before saving to SharedPreferences. Object serialization is really easy, you don't need a third party library for that.

public static byte[] serialize(Object obj) {
    ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
    ObjectOutputStream objectOS = new ObjectOutputStream(byteArrayOS);
    objectOS.writeObject(obj);
    objectOS.flush();
    return byteArrayOS.toByteArray();
}

public static Object deserialize(byte[] data) {
    ByteArrayInputStream byteArrayIS = new ByteArrayInputStream(data);
    ObjectInputStream objectIS = new ObjectInputStream(byteArrayIS);
    return objectIS.readObject();
}

The code above doesn't have try catch block for simplicity. You can add it on your own.

I have been doing this as the following by using Gson

To save sparseboolean array in SharedPreference:

public void SaveSparseBoolean() {
    SparseBooleanArray booleanArray = new SparseBooleanArray();
    SharedPreferences sP;
    sP=context.getSharedPreferences("MY_APPS_PREF",Context.MODE_PRIVATE)
    SharedPreferences.Editor editor=sP.edit();
    Gson gson=new Gson();
    editor.putString("Sparse_Array",gson.toJson(booleanArray));
    editor.commit();
}

To get the SparsebooleanArray from SharedPreferences

public SparseBooleanArray getSparseArray() {
    SparseBooleanArray booleanArray;
    SharedPreferences sP;
    sP = context.getSharedPreferences("MY_APPS_PREF", Context.MODE_PRIVATE);
    Gson gson=new Gson();
    booleanArray=gson.fromJson(sP.getString("Sparse_Array",""),SparseBooleanArray.class);
    return booleanArray;

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top