从 onLoadFinished 一次又一次调用 onLoadFinished 更新数据库

Updating DB from onLoadFinished calls onLoadFinished again and again

我有一种情况需要在某个日期插入一行并更新 activity 中特定日期之后的所有条目。

为此,我想我会在日期之后使用 LoaderManager 回调加载条目,并使用 ContentProviderOperation 数组从 onLoadFinished() 批量更新所有条目方法。

我面临的问题是我有 setNotificationUri 到游标,因此 onLoadfinished 被再次调用,它再次插入该行并且循环继续(不设置通知Uri 不适合我。

有没有优雅的解决方案来停止递归调用?

下面是我的onCreateLoaderonLoadFinished的简化代码:

@Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        //retrieve data before the start date
        mStartDate = ProjectContract.getDateFromDb(mUserProjectEntryData.getAsString(ProjectContract.ProjectEntryTable.COLUMN_DATETEXT));
        Date nextDate = Utilities.addDays(mStartDate,1);
        String sortOrder = ProjectContract.ProjectEntryTable.COLUMN_DATETEXT + " ASC";
        Uri projectEntryUri = ProjectContract.ProjectEntryTable.buildProjectEntryWithStartDateUri(mProjectId,
                ProjectContract.getDbDateString(nextDate));
        return new CursorLoader(
                this,
                projectEntryUri,
                PROJECT_ENTRY_COLUMNS,
                null,
                null,
                sortOrder
        );

    }

@Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        mDbOperations = new ArrayList<ContentProviderOperation>();
        long newTotalCount;
        String selection = ProjectContract.ProjectEntryTable.COLUMN_PROJECT_ID + " = ? AND "
                + ProjectContract.ProjectEntryTable.COLUMN_DATETEXT + " = ? ";
//Some code to calculate the entry needed
        mDbOperations.add(
                ContentProviderOperation.newInsert(ProjectContract.ProjectEntryTable.CONTENT_URI)
                        .withValues(mUserProjectEntryData)
                        .withYieldAllowed(true)
                        .build()
        );

        while (data.moveToNext()) {
data.getString(COL_DATETEXT));
            newTotalCount = mCurrentWordCount + data.getLong(COL_WORD_COUNT);
            mDbOperations.add(ContentProviderOperation.newUpdate(ProjectContract.ProjectEntryTable.CONTENT_URI)
                    .withValue(ProjectContract.ProjectEntryTable.COLUMN_TOTAL_WORD_COUNT, newTotalCount)
                    .withSelection(selection, new String[]{
                            Long.toString(data.getLong(COL_PROJECT_ID)),
                            data.getString(COL_DATETEXT)
                    })
                    .build());

        }
//Hacky solution I put in just to make the code working.
//        data.close();
        try {
            getContentResolver().applyBatch(ProjectContract.CONTENT_AUTHORITY, mDbOperations);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        }
    }

你有没有试过如下:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    Log.i(TAG, "Inside onLoadFinished");
    // Swap the new cursor in.  (The framework will take care of closing the
    // old cursor once we return.)
    mAdapter.swapCursor(data);

    // The list should now be shown.
    if (isResumed()) {
        setListShown(true);
    } else {
        setListShownNoAnimation(true);
    }
}

我最终将数据库操作移动到一个单独的线程,而没有使用加载程序回调

决定为和我一样为这个问题苦苦挣扎的人写一个答案。

我有 2 个带有外键的 table,我需要 1 table 的 _ID 在第二个中创建一个外键,这就是为什么我必须分别插入每一行(不像批量插入)。它导致我的 Loader 在每次插入后更新。我通过阻止 ContentProvider 中的插入方法调用 notifyChange 并在每次批量操作后手动通知 ContentProvider 来解决这个问题。

希望这会对某人有所帮助。

Is there any elegant solution to stop the recursive call?

解决方法很简单,关闭光标停止递归调用。只需添加 -

data.close();

applyBatch 操作后。