I have an IntentService which is supposed to send thousands of Volley requests to my server. It works fine and is very fast. I create my requests based on a Cursor I get from a ContentProvider (getContentResolver()).
I do however want to avoid making requests for items which are already available client-side. I get this list of items by calling
List<List> savedLyrics = DatabaseHelper.getInstance(this).listMetadata();
If that list is empty, it works fine. However, if it's not - then when this method
savedLyrics.contains(Arrays.asList(artist, title))
gets called, it seems to really slow things down.
public class BatchDownloaderService extends IntentService implements Response.Listener<String>, Response.ErrorListener {
private int total = 0;
private int count = 0;
private int successCount = 0;
private RequestQueue requestQueue;
private OkHttpClient client = null;
public BatchDownloaderService() {
super("Batch Downloader Service");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onHandleIntent(intent);
return START_NOT_STICKY;
}
@Override
protected void onHandleIntent(Intent intent) {
if (client == null)
getClient();
Uri content = intent.getExtras().getParcelable("uri");
List<List> savedLyrics = DatabaseHelper.getInstance(this).listMetadata();
Cursor cursor = /* Get My Cursor */;
if (cursor == null)
return;
total = cursor.getCount();
updateProgress();
final Cache cache = new DiskBasedCache(getCacheDir(), 1024*1024);
final Network network = new BasicNetwork(new OkHttp3Stack(client));
requestQueue = new RequestQueue(cache, network, 8);
requestQueue.start();
while (cursor.moveToNext()) {
String artist = cursor.getString(0);
String title = cursor.getString(1);
if (artist == null || title == null || artist.isEmpty() || title.isEmpty() || savedLyrics.contains(Arrays.asList(artist, title))) {
// If the local database already contains this item (or if null), skip the request
updateProgress();
continue;
}
try {
Request request = QuickLyricAPI.getVolleyRequest(lrc, this, this, artist, title);
requestQueue.add(request);
} catch (Exception e) {
// Stuff
}
}
cursor.close();
}
private void updateProgress() {
/* Update the progressbar in the notification */
}
@Override
public void onErrorResponse(VolleyError error) {
updateProgress();
error.printStackTrace();
}
@Override
public void onResponse(String response) {
/* Stuff */
updateProgress();
}
private void getClient() {
/* Stuff */
}
}
If I comment out the call to .contains(), then I see no difference with the list being empty and everything is smooth.
I tried to replace the list with a TreeSet() with a comparator, it didn't make it faster. I tried to use String arrays instead of Lists, it didn't make it faster. I also tried using a Countdownlatch to make it so that onHandleIntent() doesn't finish before all the requests were done. Didn't work.
- How can an IntentService slow down the whole device and even crash my SystemUI like this? I thought it was running in its own thread.
- How can checking a list (2500 items in this case) be so expensive?
Testing this on a Nextbit Robin with 7.0
Cheers