What is the meaning of ContentResolver.bulkInsert (..)?

My goal

I want to insert multiple records into sqlite packages (transactionally).

My question

I found the android.content.ContentResolver method. bulkInsert (..) is interesting, but the state of javadoc is:

This function does not give any guarantees regarding the atomicity of the inserts.

Why will android provide a method that is crippled? Can you call me your doings for non-nuclear inserts? I'm obviously going to override ContentProvider.bulkInsert(..) to ensure atomicity, so I'm not sure why it is such a phrase.

+6
android
source share
4 answers

We need to override the bulk insert method, for example, the following ...

 public class Provider extends ContentProvider { public static final Uri URI = Uri.parse("content://com.example.android.hoge/"); @Override public String getType(Uri uri) { return null; } @Override public boolean onCreate() { return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Helper helper = Helper.getInstance(getContext(), null); SQLiteDatabase sdb = helper.getReadableDatabase(); Cursor cursor = sdb.query( Table.TABLENAME, new String[]{Table.ID, Table.DATA, Table.CREATED}, selection, selectionArgs, null, null, sortOrder, null ); return cursor; } @Override public Uri insert(Uri uri, ContentValues values) { Helper helper = Helper.getInstance(getContext(), null); SQLiteDatabase sdb = helper.getWritableDatabase(); sdb.insert(Table.TABLENAME, null, values); getContext().getContentResolver().notifyChange(uri, null); return uri; } /** * super.bulkInsert is implemented the loop of insert without transaction * So we need to override it and implement transaction. */ @Override public int bulkInsert(Uri uri, ContentValues[] values) { Helper helper = Helper.getInstance(getContext(), null); SQLiteDatabase sdb = helper.getWritableDatabase(); sdb.beginTransaction(); SQLiteStatement stmt = sdb.compileStatement( "INSERT INTO `" + Table.TABLENAME + "`(`" + Table.DATA + "`, `" + Table.CREATED + "`) VALUES (?, ?);" ); int length = values.length; for(int i = 0; i < length; i++){ stmt.bindString(1, values[i].getAsString(Table.DATA)); stmt.bindLong(2, values[i].getAsLong(Table.CREATED)); stmt.executeInsert(); } sdb.setTransactionSuccessful(); sdb.endTransaction(); return length; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { Helper helper = Helper.getInstance(getContext(), null); SQLiteDatabase sdb = helper.getWritableDatabase(); int rows = sdb.update(Table.TABLENAME, values, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); return rows; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { Helper helper = Helper.getInstance(getContext(), null); SQLiteDatabase sdb = helper.getWritableDatabase(); int rows = sdb.delete(Table.TABLENAME, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); return rows; } private static class Helper extends SQLiteOpenHelper { static Helper INSTANCE = null; private Helper(Context context, CursorFactory factory) { super(context, Table.FILENAME, factory, Table.VERSION); } public static Helper getInstance(Context context, CursorFactory factory) { if (INSTANCE == null) { INSTANCE = new Helper(context, factory); } return INSTANCE; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL( "CREATE TABLE `" + Table.TABLENAME + "`(" + " `" + Table.ID + "` INTEGER PRIMARY KEY AUTOINCREMENT," + " `" + Table.CREATED + "` INTEGER," + " `" + Table.DATA + "` TEXT" + ");" ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } } 
+4
source share

Use applyBatch () instead.

This allows you to perform many different operations in a transactional manner, however, there is performance for this flexibility.

Related documentation can be found here in the ContentResolver SDK Documentation.

I gave a short guide on using applybatch in symantics backReferences

I also recommend watching this question discussing applyBatch overrides

+1
source share

This function does not give any guarantees regarding the atomicity of the Insert.

Correct me if I am wrong, but this is due to the fact that we do not know whether this content provider will bulkInsert() method if it is not our own provider. If bulkInsert () is not overridden, the default implementation will insert(Uri, ContentValues) over the values ​​and call insert(Uri, ContentValues) for each of them. This should be good if you use your own provider and know that you have implemented the bulkInsert() method, as in the following example, and use the endTransaction() method in the finally block:

  @Override public int bulkInsert(Uri uri, ContentValues[] values) { final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); final int match = sUriMatcher.match(uri); switch (match) { case WEATHER: db.beginTransaction(); int returnCount = 0; try { for (ContentValues value : values) { normalizeDate(value); long _id = db.insert(WeatherEntry.TABLE_NAME, null, value); if (_id != -1) { returnCount++; } } db.setTransactionSuccessful(); } finally { db.endTransaction(); } getContext().getContentResolver().notifyChange(uri, null); return returnCount; default: return super.bulkInsert(uri, values); } } 
+1
source share

The first add method for bulk paste in your content provider

  @Override public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { switch (uriMatcher.match(uri)) { case USERS: for (ContentValues value : values) { long rowID = sqLiteDatabase.insert(YOUR_TABLENAME, "", value); if (rowID > 0) { Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID); //append ID into CONTENT_URI getContext().getContentResolver().notifyChange(_uri, null); return values.length; //return total number of data inserted } } break; } return super.bulkInsert(uri, values); } 

Add the code below at the click of a button (Below to enter voluminous data)

  String userName = editTextUserName.getText().toString(); String userCity = editTextUserCity.getText().toString(); Log.d("BulkInsert", "onClick: -------START------"); ContentValues[] contentValue = new ContentValues[5000]; for (int i = 0; i < 5000; i++) { contentValue[i] = new ContentValues(); // initialize Array of content values //store data in content values object contentValue[i].put(UserModel.USER_CITY, userCity); contentValue[i].put(UserModel.USER_NAME, userName); contentValue[i].put(UserModel.USER_PINCODE, userPincode); } int count = getContentResolver().bulkInsert(YOUR_TABLE_URI, contentValue); //insert data Log.d("BulkInsert", "onClick: " + count); //Display number of data inserted Log.d("BulkInsert", "onClick: -------STOP------"); 
0
source share

All Articles