Android ContentResolver.bulkInsert(..)的意义是什么?

Android ContentResolver.bulkInsert(..)的意义是什么?,android,Android,我的目标 我想批量(以事务方式)将多条记录插入sqlite 我的问题 我发现方法android.content.ContentResolver(..)很有趣,但javadoc声明: 此函数不保证插入的原子性 为什么android会提供一种残废的方法?你能告诉我非原子插入的用例吗?我显然要重写ContentProvider.bulkInsert(…)以确保原子性,所以我不知道为什么会这样。改用applyBatch() 这允许您以事务方式执行许多不同的操作,但是这种灵活性会影响性能 相关文档可在中找

我的目标

我想批量(以事务方式)将多条记录插入sqlite

我的问题

我发现方法
android.content.ContentResolver
(..)很有趣,但javadoc声明:

此函数不保证插入的原子性

为什么android会提供一种残废的方法?你能告诉我非原子插入的用例吗?我显然要重写ContentProvider.bulkInsert(…)以确保原子性,所以我不知道为什么会这样。

改用applyBatch()

这允许您以事务方式执行许多不同的操作,但是这种灵活性会影响性能

相关文档可在中找到

我提供了在中使用applybatch的快速教程


我还建议查看哪些讨论覆盖applyBatch,我们需要覆盖大容量插入方法,如下所示

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) {
        }
    }
}
公共类提供程序扩展ContentProvider{
公共静态最终Uri=Uri.parse(“content://com.example.android.hoge/");
@凌驾
公共字符串getType(Uri){
返回null;
}
@凌驾
公共布尔onCreate(){
返回false;
}
@凌驾
公共游标查询(Uri Uri、字符串[]投影、字符串选择、字符串[]selectionArgs、字符串排序器){
Helper Helper=Helper.getInstance(getContext(),null);
SQLiteDatabase sdb=helper.getReadableDatabase();
Cursor=sdb.query(
Table.TABLENAME,
新字符串[]{Table.ID,Table.DATA,Table.CREATED},
选择,
精选,
无效的
无效的
巫师,
无效的
);
返回光标;
}
@凌驾
公共Uri插入(Uri、ContentValues){
Helper Helper=Helper.getInstance(getContext(),null);
SQLiteDatabase sdb=helper.getWritableDatabase();
insert(Table.TABLENAME,null,value);
getContext().getContentResolver().notifyChange(uri,null);
返回uri;
}
/**
*super.bulkInsert实现了无事务插入的循环
*所以我们需要重写它并实现事务。
*/
@凌驾
public int bulkInsert(Uri,ContentValues[]值){
Helper Helper=Helper.getInstance(getContext(),null);
SQLiteDatabase sdb=helper.getWritableDatabase();
sdb.beginTransaction();
SQLiteStatement stmt=sdb.compileStatement(
“插入到”`+Table.TABLENAME+“`(`+Table.DATA+“`,`+Table.CREATED+“`)值(?,);”
);
int length=values.length;
for(int i=0;i
此函数不保证函数的原子性 插入

如果我错了,请纠正我,因为我们不知道给定的内容提供程序是否覆盖
bulkInsert()
方法,除非它是我们自己的提供程序。如果未重写bulkInsert()方法,则默认实现将迭代这些值,并对每个值调用
insert(Uri,ContentValues)
。如果您正在使用自己的提供程序,并且知道您已经实现了
bulkInsert()
方法(如下面的示例),并且在finally块中使用
endTransaction()
方法,则应该可以:

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

首先在内容提供商中添加批量插入的方法

 @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);
}
在按钮单击中添加以下代码(执行以下操作以插入批量数据)

String userName=editTextUserName.getText().toString();
字符串userCity=editTextUserCity.getText().toString();
Log.d(“BulkInsert”、“onClick:----开始----”;
            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------");