0

I am working on an app which is able to play a list of songs. It is not primarily a music player and so multiple playlists are not required. I have been using SharedPreferences to store a list of the songs which the user has selected from their MediaStore.

I have been storing them in a SharedPreferences file as follows (pseudo-code):

Key = "Song"+n
Value = _ID

When I need to retrieve the song IDs I just loop through the file for "Song"+0 to "Song"+n

This is working fine until I need to remove a song from the list. The obvious solution is to remove the relevant song and all songs after it in the list and then replace those songs with an index number one less than they previously had.

Something about this is smelling bad to me so my questions are:

  1. Is what I have described a fundamentally bad way of storing the list?
  2. If it is bad, what would be a better alternative?
  3. If using SharedPreferences in this way is reasonable then is my idea for removing items and reindexing the list a good idea?
  4. If it is not a good idea then again, what would be a better alternative?

Thank you in advance, Andrew

user1977132
  • 487
  • 2
  • 18
  • Your question isn't completely clear... Are you storing each song key/value as a separate SharedPreferences item? – mjp66 Jan 11 '15 at 15:00

3 Answers3

0

Is what I have described a fundamentally bad way of storing the list?

If you are expecting your list to contain huge volume of data, then this is not the best way of storing the data.

Please note that SharedPreferences caches after first load, so disk access to load data will take time but once. You can try to load SharedPreferences early in your test suite to avoid this penalty.

Also, parsing a XML file and updating the data is very time consuming in android. It is not recommended.

If it is bad, what would be a better alternative?

I would recommend to insert the data into SQLite

If using SharedPreferences in this way is reasonable then is my idea for removing items and reindexing the list a good idea?

Answer is NO. Reasons stated above.

If it is not a good idea then again, what would be a better alternative?

Retrieve the data from SQLite and store them in a JSON object. Retrieving and updating if using XML will happen in seconds, by using JSON, it will happen in milliseconds.

Please feel free to add/update the answer with more details.

Prem
  • 4,823
  • 4
  • 31
  • 63
  • It is highly unlikely there will be more than 50 songs in the list, would you still suggest going down the JSON route? If so would you suggest saving it to the file system as one of the other posters suggested or serialising it and saving it in SharedPreferences? – user1977132 Jan 11 '15 at 15:29
  • @user1977132, If only 50 songs, with max 100 rows, your current approach is fine. No need to make any changes. Please note that performance tuning is needed only when you see issue in performance. If not, it is better to leave as it is. – Prem Jan 11 '15 at 15:32
  • @Prem assuming that the OP is storing each song as its own SharedPreferences entry, that kind of approach certainly is not fine, even if for just a couple dozen items. – mjp66 Jan 11 '15 at 15:50
0

See this answer for an example of storing the contents of a JSON array to SharedPreferences. You could just as well -- and probably should -- store that JSON array as a file to the device's file system with

    public void saveJSONObjectAsFile(String path, JSONObject obj){

    File mFile = new File(path);
    OutputStream outputStream = null;
    try {
        outputStream = new FileOutputStream(mFile);
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        outputStream.write(obj.toString().getBytes());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        outputStream.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }  
}

Personally, I wouldn't mess with SQLite for a relatively simple data backing like this.

Community
  • 1
  • 1
JASON G PETERSON
  • 2,193
  • 1
  • 18
  • 19
0

A very simple example of adding/removing songs from a list, using SharedPreferences (the example assumes that your song IDs are numbers)

// SharedPreferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor prefsEditor = prefs.edit();

// example song ID selected by user
int selectedSongId = 123;

// example of deleting a song ID...
try {
    // get currently stored songs list
    JSONArray currentItems = new JSONArray(prefs.getString("songs", new JSONArray().toString()));
    // init a new empty songs list
    JSONArray updatedItems = new JSONArray();
    for (int i = 0; i < currentItems.length(); i++) {
        // loop through currently stored list, put each item into new list
        // except for the Id user has selected to delete
        int songId = currentItems.getInt(i);
        if (songId != selectedSongId) {
            updatedItems.put(songId);
        }
    }
    // replace old songs list with the new list and save to SharedPreferences
    prefsEditor.putString("songs", currentItems.toString()).commit();
} catch (JSONException e) {
    e.printStackTrace();
}

// example of adding a song ID to existing songs list
try {
    // get currently stored songs list
    JSONArray currentItems = new JSONArray(prefs.getString("songs", new JSONArray().toString()));
    // add new song Id to list
    currentItems.put(selectedSongId);
    // save updated songs list back to SharedPreferences
    prefsEditor.putString("songs", currentItems.toString()).commit();
} catch (JSONException e) {
    e.printStackTrace();
}

There are far more efficient ways of doing this but this simplified example hopefully helps point you in a good direction ;)

PS - I typed up the example without running it, there might be an error somewhere

mjp66
  • 4,214
  • 6
  • 26
  • 31