Search code examples
androidandroid-asynctaskandroid-sqlitesqliteopenhelper

Android SQLiteDatabase transaction and AsyncTasc issue


I think I am missing something and maybe one of you can give me a hint.

Here is what I have:

  • an AsyncTask with many for loops which takes paginated data from a web service
  • a SQLiteDatabase which stores the retrieved data
  • the user has the possibility to cancel the thread at any time by pressing a button, case in which all the inserted/processed data needs to be removed.

Here is how I thought of it:

public class DBAdapter {
private static SQLiteDatabase database;
private static boolean isTransactionRunning;

public void beginTransaction() {
        database.beginTransaction();
        isTransactionRunning = true;
    }

public void endTransaction() {
        database.setTransactionSuccessful();
        database.endTransaction();
        isTransactionRunning = false;
    }

public void rollbackTransaction() {
        database.endTransaction();
        isTransactionRunning = false;
    }
}

and on my activity I open the database and start the asynctask

protected class GetUserDataTask extends AsyncTask<Boolean, Bundle, Bundle> {
    @Override
        protected Bundle doInBackground(Boolean... values) {

         db.beginTransaction();

         for (Object obj : response.getData()) {
            if (isCancelled()) {
                return null;
            }
          ///some processing

         for (Object obj : response.getData()) {
            if (isCancelled()) {
                return null;
            }
      }

       @Override
        protected void onCancelled() {
            super.onCancelled();

            if (db.isTransactionRunning()) {
                db.rollbackTransaction();
            }
        }
     }

       @Override
        protected void onPostExecute(Bundle result) {
           if (db.isTransactionRunning()) {
            if (!error){
              db.endTransaction()
            } else{
                db.rollbackTransaction();
            }
     }

The error I am getting, when I cancel the AsyncTask is:

java.lang.IllegalStateException: Cannot perform this operation because there is no current transaction.

and it is happening when it fires withing onCancelled().

What am I doing wrong?


Solution

  • Is there a reason why you have so many places where you handle commit/rollback?

    I donot know why the error happens.

    But maybe it will be helpfull, if you simplify the code

    • eleminate the static DBAdapter.isTransactionRunning
    • handle beginTransaction, endTransaction and rollbackTransaction in one block

    like this:

    protected class GetUserDataTask extends AsyncTask<Boolean, Bundle, Bundle> {
        @Override
            protected Bundle doInBackground(Boolean... values) {
                boolean inTransaction = true;
                try {
                     db.beginTransaction();
    
                     for (Object obj : response.getData()) {
                        if (isCancelled()) {
                            return null;
                        }
                      ///some processing
                     }
    
                     for (Object obj : response.getData()) {
                        if (isCancelled()) {
                            return null;
                        }
                     }
    
                    if (isCancelled()) {
                        return null;
                    }
    
                    // every thing worked well without cancel
                    inTransaction = false;
                    db.endTransaction();
                    return processingResult;
    
                } finally {
                    if (inTransaction) {
                        db.rollbackTransaction();
                    }
                }
            }