目标:从XML数据刷新数据库
过程:
开始交易
从表中删除所有现有行
每个解析XML的主要元素插入主表并获取PK
每个主元素的子元素将记录插入到第二个表中,从上一步提供FK
提交交易
数据库操作相当标准的东西.问题是CRUD操作不是在内部完成,ContentProvider
而是使用ContentResolver
插件,例如看起来像resolver.insert(CONTENT_URI, contentValues)
.ContentResolver API似乎没有任何与事务相关的东西,我无法使用,bulkInsert
因为我间歇性地插入2个表(另外我也希望delete
在事务内部).
我正在考虑ContentProvider
通过使用注册我自定义的监听器,registerContentObserver
但由于ContentResolver#acquireProvider
隐藏了方法,我如何获得正确的引用?
我运气不好吗?
我已经看到了在谷歌I/O应用程序的源代码,它们覆盖ContentProvider
的applyBatch()
它的内部方法和使用交易.所以,你创建一批ContentProviderOperation
s然后调用getContentResolver().applyBatch(uri_authority, batch)
.
我打算用这种方法看看它是如何工作的.我很好奇是否有其他人尝试过它.
从kaciula提到的使用ContentProviderOperation的Android 2.1以来,可以相当干净地进行基于事务的多表插入.
构建ContentProviderOperation对象时,可以调用.withValueBackReference(fieldName,refNr).使用applyBatch应用操作时,结果是insert()调用提供的ContentValues对象将注入一个整数.整数将使用fieldName String键入,并且其值将从之前应用的ContentProviderOperation的ContentProviderResult中检索,由refNr索引.
请参阅下面的代码示例.在示例中,在table1中插入一行,然后在表2中插入行时将结果ID(在本例中为"1")用作值.为简便起见,ContentProvider未连接到数据库.在ContentProvider中,有一些打印输出适合添加事务处理.
public class BatchTestActivity extends Activity { /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ArrayListlist = 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 }