본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] ContentProviderOperation 에 대한 짧은 이야기

by 돼지왕 왕돼지 2017. 4. 15.
반응형

 [android] ContentProviderOperation 에 대한 짧은 이야기


https://www.grokkingandroid.com/better-performance-with-contentprovideroperation/

http://stackoverflow.com/questions/4655291/semantics-of-withvaluebackreference

https://developer.android.com/reference/android/content/ContentProviderOperation.Builder.html


Android, applybatch, ArrayList, batch, batch operation, Builder, COMMIT, contentprovideroperation, Context Switching, CREATE, data, db access, Delete, LOCK, nerinsert, newdelete, newupdate, Operation, Performance, previousresult, rawcontact, static build method, sync adapter, transaction, Update, withselection, withvalue, withValueBackReference, withvalues, withYieldAllowd, yield, yield point, [android] ContentProviderOperation 에 대한 짧은 이야기, 효율성


-

여러 개의 data 에 대하 Create, Delete, Update 를 수행하려면 ContentProviderOperation 을 사용하여 batch 를 돌리는 것이 추천된다.



-

ContentProviderOperation 을 사용하면 다음의 장점이 있다.

     모든 operation 이 한 개의 transaction 으로 처리된다.

     transaction 을 열고 닫고 등을 효율적으로 하여 performance 가 좋아진다.

     context switching 단계가 줄어들어 performance 가 좋아진다.



-

ContentProviderOperation 은 Builder 를 사용하여 만들 수 있다.

다음 3개의 static build method 를 제공한다.

     newInsert

     newUpdate

     newDelete 



-

builder 에는 다음의 함수들이 있다.

withSelection( String selection, String[] selectionArgs )

withValue(String key, Object value)

withValues(ContentValues values)

withValueBackReference(String value, int previousResult)

withValueBackReferences(ContentValues values)

withYieldAllowd(boolean isYieldAllowed)



-

withValueBackReference 는 다음과 같은 경우에 사용되기 좋다.


예를 들어 rawContact 을 하나 insert 하고, 해당 rawContact 에 phone number 를 추가하고 싶다면.. 

ArrayList 로 전달된 ops 수행 도중 새로 추가된 rawContact 의 id 를 알아야 한다.


이 때 ops 수행 도중 생성된 값을 알아내기 위해 사용되는 녀석이 바로 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) // 0 은 operation index 0번째에 수행된 녀석의 결과를 이용한다는 이야기

     .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)

     .withValue(Phone.NUMBER, phoneNumber)

     .withValue(Phone.TYPE, Phone.TYPE_HOME)

     .withValue(Phone.LABEL, label)

     .build());


...


getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);



-

batch operation 을 수행할 때 그 양이 매우 많으면 다른 db access 를 막으면서 문제가 발생할 수 있다.

이런 오랜 락을 방지하기 위해서 yield point 를 batch operation 중간에 넣을 수 있다.

yield 가 발생하면 그 이전에 발생한 operation 들을 commit 하고 다른 db access 에 권한을 yield 한 후에 다른 transaction 을 열어 나머지를 처리한다.


yield point 에서 무조건 commit 을 하는 것은 아니고, 다른 db access 가 있을 경우에만 그렇게 한다.


보통 sync adapter 들이 새로운 raw contact operation 을 추가하기 전에 yield 를 한번씩 수행하곤 한다.



-

마지막에 applyBatch 시점에는 이 operation 들이 ArrayList 형태로 전달되어야 한다.





반응형

댓글