■ContentProvider
以下のようにbulkInsertメソッドをOverrideする。
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クラスでinsertを普通に呼ぶようなのでcompileStatementの処理を自前で書く */ @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) { } } }
super.bulkInsert(uri, values)は内部でinsert(uri, values)を複数回呼び出すようになっており、Insert文が複数回発行されて非常に遅くなる。
■クライアントコード
ContentValues[] contentValues = new ContentValues[length]; for(int i = 0; i < length; i++){ ContentValues values = new ContentValues(); values.put(DATA, "data_" + i); values.put(CREATED, new Date().getTime()); contentValues[i] = values; } getApplicationContext().getContentResolver().bulkInsert(Provider.URI, contentValues);