Android: SQLite transactions when using ContentResolver

前端 未结 4 1946
一个人的身影
一个人的身影 2020-12-12 14:30

The goal: refresh database from XML data

The process:

  • Start transaction
  • Delete all existing rows from the ta
4条回答
  •  难免孤独
    2020-12-12 15:08

    It is possible to do transaction based multi table inserts rather cleanly since Android 2.1 by using ContentProviderOperation, as mentioned by kaciula.

    When you build the ContentProviderOperation object, you can call .withValueBackReference(fieldName, refNr). When the operation is applied using applyBatch, the result is that the ContentValues object that is supplied with the insert() call will have an integer injected. The integer will be keyed with the fieldName String, and its value is retrieved from the ContentProviderResult of a previously applied ContentProviderOperation, indexed by refNr.

    Please refer to the code sample below. In the sample, a row is inserted in table1, and the resulting ID (in this case "1") is then used as a value when inserting the row in table 2. For brevity, the ContentProvider is not connected to a database. In the ContentProvider, there are printouts where it would be suitable to add the transaction handling.

    public class BatchTestActivity extends Activity {
        /** Called when the activity is first created. */
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            ArrayList list = new
                ArrayList();
    
            list.add(ContentProviderOperation.
                newInsert(BatchContentProvider.FIRST_URI).build());
            ContentValues cv = new ContentValues();
            cv.put("name", "second_name");
            cv.put("refId", 23);
    
            // In this example, "refId" in the contentValues will be overwritten by
            // the result from the first insert operation, indexed by 0
            list.add(ContentProviderOperation.
                newInsert(BatchContentProvider.SECOND_URI).
                withValues(cv).withValueBackReference("refId", 0).build());
    
            try {
                getContentResolver().applyBatch(
                    BatchContentProvider.AUTHORITY, list);
            } catch (RemoteException e) {
                e.printStackTrace();
            } catch (OperationApplicationException e) {
                e.printStackTrace();
            }
        }
    }
    
    public class BatchContentProvider extends ContentProvider {
    
        private static final String SCHEME = "content://";
        public static final String AUTHORITY = "com.test.batch";
    
        public static final Uri FIRST_URI =
            Uri.parse(SCHEME + AUTHORITY + "/" + "table1");
        public static final Uri SECOND_URI =
            Uri.parse(SCHEME + AUTHORITY + "/" + "table2");
    
    
        public ContentProviderResult[] applyBatch(
            ArrayList operations)
                throws OperationApplicationException {
            System.out.println("starting transaction");
            ContentProviderResult[] result;
            try {
                result = super.applyBatch(operations);
            } catch (OperationApplicationException e) {
                System.out.println("aborting transaction");
                throw e;
            }
            System.out.println("ending transaction");
            return result;
        }
    
        public Uri insert(Uri uri, ContentValues values) {
            // this printout will have a proper value when
            // the second operation is applied
            System.out.println("" + values);
    
            return ContentUris.withAppendedId(uri, 1);
        }
    
        // other overrides omitted for brevity
    }
    

提交回复
热议问题