1

I want to run my Content Resolver operations (query, insert, delete) in a background thread.

I found out the AsyncQueryHandler could solve my problem. The problem with AsyncQueryHandler is: bulk insert. I have this kind of operation in my app, and in the AsyncQueryHandler class doesn't have a bulkInsert method to be overwritten.

How could I handle bulk insert when dealing with AsyncQueryHandler? Is there another option besides the AsyncQueryHandler?

Guilherme Lima Pereira
  • 1,402
  • 5
  • 17
  • 35

3 Answers3

1

Hey you can use CursorLoader in this case. This will query content resolver and returns a cursor. it uses AsyncTaskLoader to perform the cursor query on a background thread so that it does not block the application's UI. you can look at http://www.theappguruz.com/blog/use-android-cursorloader-example for more details.

And you can define bulk insert method into your content providers like below

@Override
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
    //mOpenHelper is object of helper class.
    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();


            db.beginTransaction();
            int rowsInserted = 0;
            try {
                for (ContentValues value : values) {

                    long _id = db.insert(TABLE_NAME, null, value);
                    if (_id != -1) {
                        rowsInserted++;
                    }
                }
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }

            if (rowsInserted > 0) {
                getContext().getContentResolver().notifyChange(uri, null);
            }
            return rowsInserted;


}
Rohan Sharma
  • 374
  • 4
  • 11
  • The problem with CursorLoader is when I need to make insert and delete operations. I can't use it for these operations. – Guilherme Lima Pereira May 14 '17 at 18:09
  • you can refer to this link for more details http://stackoverflow.com/questions/11131058/how-to-properly-insert-values-into-the-sqlite-database-using-contentproviders-i – Rohan Sharma May 14 '17 at 18:17
  • I've seen this answer. The guys tells to use the "getContentResolver().insert(Uri, ContentValues);". The problem is: this kind of insertion goes on main thread ui. I need to make insertion on a background thread. – Guilherme Lima Pereira May 14 '17 at 18:21
  • if you want to run your insertion in background thread then you can use AsyncTask for that. – Rohan Sharma May 14 '17 at 19:02
0

At the end of the day, I changed my architecture.

I removed the bulkInsert and made a interation over the Content Values array. This way I can use the AsyncQueryHandler without problems.

After thinking and thinking, I concluded this is the best option for me.

Guilherme Lima Pereira
  • 1,402
  • 5
  • 17
  • 35
0

AsyncQueryHandler doesn't support bulkInsert probably because this method makes no guarantees about the atomicity of the insertions. What does this mean? Well, if startInsert fails for some reason, then there is no insertions done. This means you can have either No insertions made, or One insertion made. There are only 2 options. Atomicity is maintained, i.e, if failed the underlying data source remain the same as before.

If bulkInsert of 10 items should fail in the middle for some reason, there can be many options: 3 items are inserted or 5 items are inserted. Thus there is no atomicity. This happens when the ContentProvider doesn't override bulkInsert and ends up using the implicit insert multiple times. So after each item is inserted, the transaction is considered successful and the commit is made. This means for 10 items, 10 transactions occur, and if any one fails in between, there is no rolling back to the previous state of the data source. The atomicity of the operation is lost.

But this is bad. What if you own the ContentProvider and you have overridden bulkInsert and ensured atomicity is maintained. Then you should be able to use AsyncQueryHandler to perform bulkInsert. https://github.com/Madrapps/AsyncQuery library does exactly that. It's the same AsyncQueryHandler of Android, but supports bulkInsert.

Just make sure you use your own ContentProvider that could handle bulkInsert if you are concerned about atomicity.

Henry
  • 17,490
  • 7
  • 63
  • 98