Почему моя пакетная операция ContentResolver содержит только 7 из 21 записей? - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть три фрагмента в FragmentPagerAdapter, и каждый из них извлекает список кадров / данных с сервера, используя Volley. Эти данные позже будут использованы для обновления RecyclerView Адаптера фрагмента в качестве курсора.

    VolleyRestClientUtils.get(getString(R.string.PATH_SHOP), LOG_TAG, params, true, false, new JsonHttpResponseHandler() {
        public void onSuccess(JSONObject response) {
            Log.d(LOG_TAG, "request Response : " + response.toString());
            try {
                String status = response.getString("status");
                if (RestClientUtils.STATUS_OK.equals(status)) {
                    final JSONArray frames = response.getJSONArray("items");
                    Log.d(LOG_TAG, "request Response : " + frames.length());
                    if (frames != null && frames.length() > 0) {
                        new AsyncTask<Void, Void, Boolean>() {
                            @Override
                            protected Boolean doInBackground(Void... voids) {
                                List<ContentValues> listShopFrame = ShopFrame.fromJSONArray(frames, sort);
                                if (listShopFrame.size() > 0 && isActivityActive()) {
                                    ContentResolver cr = getActivity().getContentResolver();
                                    if (!isRequestMore) {
                                        cr.delete(ShopFrame.CONTENT_URI, ShopFrame.COLUMN_CATEGORY + "=?",
                                                new String[]{sort});
                                        paramSkip = frames.length();
                                    } else {
                                        paramSkip += frames.length();
                                    }

                                    ArrayList<ContentProviderOperation> operations = new ArrayList<>();
                                    String log = listShopFrame.size()+" ";
                                    for (int i = 0; i < listShopFrame.size(); i++) {
                                        operations.add(ContentProviderOperation
                                                .newInsert(ShopFrame.CONTENT_URI)
                                                .withValues(listShopFrame.get(i))
                                                .build());
                                        log += listShopFrame.get(i).toString()+"\n";
                                    }
                                    Log.i("loader_callback_"+sort, log);
                                    //cr.applyBatch(ShopFrame.CONTENT_AUTHORITY, operations);
                                    ContentValues[] opsAsArray = new ContentValues[listShopFrame.size()];
                                    listShopFrame.toArray(opsAsArray);
                                    cr.bulkInsert(ShopFrame.CONTENT_URI, opsAsArray);
                                    //return true;
                                }
                                return true;
                            }

                            @Override
                            protected void onPostExecute(Boolean result) {
                                dataRefreshed = true;
                                Log.i("loader_callback_"+sort, "response post execute");
                                if (result) {
                                    loadSucceed();
                                    PicMixApp.getInstance().setRefreshed(ShopFrameFragment.this.getClass().getName());
                                } else {
                                    loadFailed(null);
                                }
                            }
                        }.execute();
                    } else {
                        //TODO
                        //Handle error
                        loadFailed(getString(R.string.err_load_s, getString(R.string.frame)));
                    }
                } else if (VolleyRestClientUtils.STATUS_RESOURCE_NOT_FOUND.equals(status)) {
                    hasMore = false;
                    loadSucceed();
                } else {
                    loadFailed(getString(R.string.err_load_s, getString(R.string.frame)));
                }
            } catch (Exception e) {
                Log.e(LOG_TAG, "Exception:" + e.getMessage());
                loadFailed(getString(R.string.err_load_s, getString(R.string.frame)));
            }
        }

        @Override
        public void onJSONError(String responseString) {
            loadFailed(getString(R.string.err_load_s, getString(R.string.frame)));
        }

        @Override
        public void onFailure(String errMessage, int statusCode, Map<String, String> headers, byte[] responseBytes) {
            loadFailed(getString(R.string.err_load_s, getString(R.string.frame)));
        }
    });

Принимая во внимание, что loadSucceed() имеет следующий код:

if (this.recyclerView != null) {
        final RecyclerView.Adapter adapter = recyclerView.getAdapter();
        if (adapter != null) {
            adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
                @Override
                public void onChanged() {
                    super.onChanged();
                    Log.i(DefaultRecyclerFragment.this.getClass().getName(), "onChanged");
                    adapter.unregisterAdapterDataObserver(this);
                    isLoading = false;
                }

                public void onItemRangeRemoved(int positionStart, int itemCount) {
                    Log.i(DefaultRecyclerFragment.this.getClass().getName(), "onItemRangeRemoved:" + positionStart + ", itemcount:" + itemCount);
                    adapter.unregisterAdapterDataObserver(this);
                    isLoading = false;
                }
            });

            if (adapter instanceof CursorRecyclerAdapter && loadMoreView != null) {
                ((CursorRecyclerAdapter) adapter).removeFooter(loadMoreView);
            }
        }
    }

Я поместил код для инициализации загрузчика в методе onResume() каждого фрагмента:

int id = 100+Integer.valueOf(sort);
Loader l = getLoaderManager().getLoader(id);
Log.i("loader_callback_"+sort, "success loading volley "+l);
if(l == null) {
    getLoaderManager().restartLoader(id, null, this);
}

Моя проблема в том, что, похоже, происходит какое-то состояние гонки, что адаптер просматриваемого фрагмента обновляется дважды, а иногда и трижды. Начальный курсор, выбранный фрагментом Loader фрагмента, имеет 10 строк, конечно, но после обновления большую часть времени он имеет только 7 из 21 строки, которые, как ожидается, будут вставлены.

Я думал, что все операции ContentResolvers являются синхронными (могут выполняться только одна за другой, а не одновременно). Что здесь происходит?

РЕДАКТИРОВАТЬ: Должен ли я просто ввести код инициализации загрузчика в loadSuccess() обратный вызов?

EDIT2: я должен отметить, что эти фрагменты расширяются android.support.v4.app.Fragment, и я использую версию 27.1.1 библиотеки поддержки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...