日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ContentProviderOperation批量操作提升性能

發布時間:2025/4/16 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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對象

ArrayList<ContentProviderOperation> ops =new ArrayList<ContentProviderOperation>(); ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI).withValue(RawContacts.ACCOUNT_TYPE, "someAccountType").withValue(RawContacts.ACCOUNT_NAME, "someAccountName").withYieldAllowed(true).build());

當然 你還可以使用熟悉的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 points

  • withValueBackReference(String key, int previousResult)
    在Android中 創建一個聯系人,需要先創建一個Raw Contact,然后再創建其他附件的數據(電話號碼、email、地址等)。而后面的操作需要Raw Contact的ID值作為外鍵。 由于用到了 ContentProviderOperation,第一步Raw Contact的id還沒有生成呢。 這個時候就可以使用withValueBackReference 函數來實現該功能了。在withValueBackReference 函數中第一個參數為 本次操作數據字段的名稱 ;第二個參數為 需要引用前面某一次操作的序號

ops = new ArrayList<ContentProviderOperation>(); ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI).withValue(RawContacts.ACCOUNT_TYPE, someAccountType).withValue(RawContacts.ACCOUNT_NAME, someAccountName).build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0).withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE).withValue(StructuredName.DISPLAY_NAME, displayName).withValue(StructuredName.FAMILY_NAME, lastName).withValue(StructuredName.GIVEN_NAME, firstName).build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0).withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, phoneNumber).withValue(Phone.TYPE, Phone.TYPE_HOME).withValue(Phone.LABEL, label).build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0).withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE).withValue(Event.TYPE, Event.TYPE_BIRTHDAY).withValue(Event.START_DATE, dateStr).build()); try {getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (RemoteException e) {// some error handling } catch (OperationApplicationException e) {// some error handling }

注意

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批量操作提升性能的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。