Reputation: 936
I'm building a music player app on Android and I'm having trouble loading the list of songs on the device quickly. It loads 577 songs in about 6.8-7 seconds, which is entirely too long. Any tips?
I'm trying to get the following information: Song
Here is my current algorithm:
public static ArrayList<Song> getSongList(Activity activity, String artistBound, Album albumBound) {
long start = System.currentTimeMillis();
ArrayList<Song> songList = new ArrayList<>();
ContentResolver musicResolver = activity.getContentResolver();
Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
if(musicCursor!=null && musicCursor.moveToFirst()){
//get columns
int titleColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.TITLE);
int idColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media._ID);
int artistColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.ARTIST);
int albumIdColumn = musicCursor.getColumnIndex
(MediaStore.Audio.Media.ALBUM_ID);
int ringColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.IS_RINGTONE);
int notifColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.IS_NOTIFICATION);
//add songs to list
do {
long thisId = musicCursor.getLong(idColumn);
String thisTitle = musicCursor.getString(titleColumn);
Artist thisArtist = new Artist(musicCursor.getString(artistColumn));
if(artistBound != null && !thisArtist.getName().equals(artistBound)) continue;
long albumId = musicCursor.getLong(albumIdColumn);
Cursor albumCursor = activity.getContentResolver().query(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Audio.Albums.ALBUM_ART, MediaStore.Audio.Albums.ALBUM},
MediaStore.Audio.Albums._ID + " = ?",
new String[]{Long.toString(albumId)},
null
);
boolean queryResult = albumCursor.moveToFirst();
String albumCover = null;
String albumName = null;
Album album = null;
if (queryResult) {
albumCover = albumCursor.getString(0);
albumName = albumCursor.getString(1);
album = new Album(albumName, albumCover);
}
albumCursor.close();
if(musicCursor.getInt(ringColumn) > 0 || musicCursor.getInt(notifColumn) > 0) {
} else {
if(albumBound == null || albumBound.getName().equals(album.getName())) {
songList.add(new Song(thisId, thisTitle, thisArtist, album));
}
}
}
while (musicCursor.moveToNext());
}
Collections.sort(songList);
Log.d("app", "Got " + songList.size() + " songs in: " + (System.currentTimeMillis() - start) + "ms");
return songList;
}
The issue is, I'm trying to load this list at the beginning, as the first screen for the music player is the list of songs. But as it is right now, the app hangs on this screen as it tries to load.
EDIT: Removing the code that searches for Album info makes it run incredibly fast. How can I optimize the album info searching?
Upvotes: 1
Views: 363
Reputation: 1829
One of the solutions is to use a lazy loading method. The idea is that you do not load all of the entries, but let say half of the data set. In your case, that will dramatically decrease the loading time. On the internet you can find several lazy loading implementations of fetching images from a server and displaying them. You can edit it in a way to read the songs from the local storage instead. Check the accepted answer here.
Upvotes: 2