Search code examples
androidcursorandroid-contentproviderloaderandroid-cursorloader

Updating DB from onLoadFinished calls onLoadFinished again and again


I have a situation in which I need to insert a row at a date and update all the entries after a particular date in an activity.

For this, I thought I'll load the entries after the date with a LoaderManager Callback and use a ContentProviderOperation array to update all of it in batch from the onLoadFinished() method.

The problem I am facing is that I have setNotificationUri to the cursor and because of that the onLoadfinished is called again, which inserts the row again and the cycle continues (not setting the notification Uri is not an option for me).

Is there any elegant solution to stop the recursive call?

Below is the simplified code of my onCreateLoader and onLoadFinished:

@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();
        }
    }

Solution

  • I ended up moving the db operations to a separate thread without using the loader callbacks