通过 IntentService 在 Sqlite 数据库中存储内容会阻塞 UI 线程

Storing content in Sqlite database through IntentService blocks the UI thread

我有很多从网络服务中提取的记录,我需要将它们缓存在本地。在执行此操作时(超过 1000 条记录),UI 线程被阻止并且我收到 ANR 警告。我认为为此使用 IntentService 不会阻止 UI。我做错了什么?

几个代码片段:

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 { 私有 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();
            }
    }
}

}

首先,永远不要从 IntentService 做一些异步的事情。一旦onHandleIntent()returns,IntentService就会被销毁。在你的情况下,网络 I/O 可能还在继续,更不用说磁盘 I/O.

其次,onResponse()是在主应用程序线程上调用的,这是您遇到困难的根源。

因此,使用 execute() 而不是 enqueue(),并直接在用于 onHandleIntent().

的线程上的 IntentService 中完成所有工作