Reputation: 1269
I have lots of records which I pull from the webservice and I need to cache them locally. While doing this (over 1000 records) the UI thread is blocked and I get ANR warning. I thought that using IntentService for that will not block the UI. What as I doiung wrong?
Few code snippets:
public class ContentIntentService extends IntentService {
@Override
protected void onHandleIntent(Intent workIntent) {
code = workIntent.getStringExtra("CODE");
getContent(code);
}
private void getContent(final String code) {
if (apiService == null) {
Retrofit client = ApiClient.getClient();
if (client != null)
apiService = client.create(ApiInterface.class);
}
if (apiService == null) {
MobileValetHelper.onConnectionFailed(mAppContext);
return;
}
Call<SectionsResponse> call = apiService.getOutletContent(outletCode, outletCode, MobileValetHelper.getContentSessionToken(mAppContext));
call.enqueue(new Callback<SectionsResponse>() {
@Override
public void onResponse(@NonNull Call<SectionsResponse> call, @NonNull Response<SectionsResponse> response) {
if (response != null
&& response.body() != null
&& response.body().status != null
&& response.body().status.equalsIgnoreCase("Success")
&& response.body().sessionToken != null
&& response.body().data != null
) {
DataCacheHelper dataCacheHelper = new DataCacheHelper(ContentIntentService.this);
dataCacheHelper.insertItems(ContentIntentService.this, items);
}
} else if (response != null
&& response.errorBody() != null) {
Log.e(TAG, "getContent response.errorBody(): " + response.errorBody().string());
}
}
@Override
public void onFailure(@NonNull Call<SectionsResponse> call, @NonNull Throwable t) {
Log.e(TAG, "getContent onFailure: " + t.toString());
}
});
}
}
public class DataCacheHelper { private ContentIntentService mIntentService;
public DataCacheHelper(ContentIntentService service) {
mIntentService = service;
}
public void insertItems(final ArrayList<CategoryItem> items) {
if (mIntentService != null && items != null) {
try {
ContentValues[] valueList = new ContentValues[items.size()];
int i = 0;
ContentValues values;
for (final CategoryItem item : items) {
values = ItemsTable.getContentValues(item);
valueList[i++] = values;
}
context.getContentResolver().bulkInsert(provider.CONTENT_URI, valueList);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Upvotes: 0
Views: 243
Reputation: 1007359
First, never do something asynchronous from an IntentService
. Once onHandleIntent()
returns, the IntentService
will be destroyed. In your case, the network I/O may still be going on, let alone the disk I/O.
Second, onResponse()
is called on the main application thread, which is the source of your difficulty.
So, use execute()
instead of enqueue()
and do all of the work directly in the IntentService
on the thread used for onHandleIntent()
.
Upvotes: 1