ContentProviderOperation批量操作提升性能
原文出處:http://blog.csdn.net/imuhao/article/details/52002995
ContentProviders 是Android 系統核心組件之一,ContentProviders 封裝了數據的訪問接口,其底層數據一般都是保存在數據庫中或者保存在云端。
有時候你需要更新多行數據,可以選擇調用多次ContentResolver的對應函數,或者 使用批量操作。當然 后者性能會比較好些。
為了使批量更新、插入、刪除數據更加方便,android系統引入了 ContentProviderOperation類。
在官方開發文檔中推薦使用ContentProviderOperations,有一下原因:
- 所有的操作都在一個事務中執行,這樣可以保證數據完整性
- 由于批量操作在一個事務中執行,只需要打開和關閉一個事務,比多次打開關閉多個事務性能要好些
- 使用批量操作和多次單個操作相比,減少了應用和ContentProvider之間的上下文切換,這樣也會提升應用的性能,并且減少占用CPU的時間,當然也會減少電量的消耗。
要創建ContentProviderOperation對象,則需要使用 ContentProviderOperation.Builder類,通過調用下面幾個靜態函數來獲取一個Builder 對象:
| newInsert () | 創建一個用于執行插入操作的Builder |
| newUpdate () | 創建一個用于執行更新操作的Builder |
| newDelete() | 創建一個用于執行刪除操作的Builder |
Builder設計模式,鏈式編程生成ContentProviderOperation對象
當然 你還可以使用熟悉的ContentValues對象,對應的函數為withValues(values)。
Builder對象核心函數
withSelection (String selection, String[] selectionArgs)
指定需要操作的數據條件。只有在更新、刪除操作中有用。withValue (String key, Object value)
定義一列的數據值。只在更新、插入數據中有用。withValues (ContentValues values)
定義多列的數據值。 只在更新、插入數據中有用withYieldAllowed(boolean)
批量操作一大堆數據可能會長期鎖定數據庫,從而阻止其他應用訪問該數據庫并且有可能會引起ANR(應用無響應)對話框出現。
為了避免長期鎖定數據庫,只要在批量操作中添加“yield points”即可。一個yield points告訴Content Provider,在執行下一個操作之前可以先提交當前的數據,然后通知其他應用,如果有其他應用請求數據的話,就先讓其他應用操作,等其他應用操作完成后,再繼續打開一個事務來執行下一個操作。如果沒有其他程序請求數據,則一個yield points不會自動提交事務,而是繼續執行下一個批量操作。通常情況下一個同步Adapter應該在開始操作一行原數據之前添加一個yield pointswithValueBackReference(String key, int previousResult)
在Android中 創建一個聯系人,需要先創建一個Raw Contact,然后再創建其他附件的數據(電話號碼、email、地址等)。而后面的操作需要Raw Contact的ID值作為外鍵。 由于用到了 ContentProviderOperation,第一步Raw Contact的id還沒有生成呢。 這個時候就可以使用withValueBackReference 函數來實現該功能了。在withValueBackReference 函數中第一個參數為 本次操作數據字段的名稱 ;第二個參數為 需要引用前面某一次操作的序號
注意
ContentProviderOperation是放到一個ArrayList中的,第一個(序號為0)操作創建了一個Row Contact,后續的幾個操作分別需要第一個操作返貨的ID值,該值對應的數據列名稱為Data.RAW_CONTACT_ID,所以
withValueBackReference(Data.RAW_CONTACT_ID, 0)兩個參數分別為Data.RAW_CONTACT_ID 和 0最后通過ContentResolver 的applyBatch()函數來應用批量操作:
try {getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (RemoteException e) {// do s.th. } catch (OperationApplicationException e) {// do s.th. }批量操作很簡單,提升性能很容易!
批量添加聯系人
public static void batchAddContact(Context context, List<FriendBean> list) throws RemoteException, OperationApplicationException {ArrayList<ContentProviderOperation> ops = new ArrayList<>();int rawContactInsertIndex = 0;for (FriendBean contact : list) {rawContactInsertIndex = ops.size(); // 有了它才能給真正的實現批量添加ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null).withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null).withYieldAllowed(true).build());// 添加姓名ops.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI).withValueBackReference(ContactsContract.Contacts.Data.RAW_CONTACT_ID,rawContactInsertIndex).withValue(ContactsContract.Contacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE).withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName()).withYieldAllowed(true).build());// 添加號碼ops.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI).withValueBackReference(ContactsContract.Contacts.Data.RAW_CONTACT_ID,rawContactInsertIndex).withValue(ContactsContract.Contacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE).withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, contact.getPhone()).withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE).withValue(ContactsContract.CommonDataKinds.Phone.LABEL, "").withYieldAllowed(true).build());}// 真正添加context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);}批量刪除聯系人
public static void batchDeleteContact(Context context, List<FriendBean> list) throws RemoteException, OperationApplicationException {ArrayList<ContentProviderOperation> ops = new ArrayList<>();for (FriendBean contact : list) {String name = contact.getName();//根據姓名求idUri uri = Uri.parse("content://com.android.contacts/raw_contacts");ContentResolver resolver = context.getContentResolver();Cursor cursor = resolver.query(uri, new String[]{ContactsContract.Data._ID},"display_name=?", new String[]{name}, null);if(cursor.moveToFirst()){int id = cursor.getInt(0);//根據id刪除data中的相應數據ops.add(ContentProviderOperation.newDelete(uri).withSelection("display_name=?",new String[]{name}).build());uri = Uri.parse("content://com.android.contacts/data");ops.add(ContentProviderOperation.newDelete(uri).withSelection("raw_contact_id=?",new String[]{id + ""}).build());}}context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);}總結
以上是生活随笔為你收集整理的ContentProviderOperation批量操作提升性能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内存分析工具MAT的使用
- 下一篇: Java中的synchronized与v