[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
-
여러 개의 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 형태로 전달되어야 한다.
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[Java Concurrency] 객체공유 (0) | 2017.04.17 |
---|---|
[android] TransactionTooLargeException 에 대한 이야기 (2) | 2017.04.16 |
[Java Concurrency] 스레드 안전성 (2) | 2017.04.14 |
[android] ListView 에서 RecyclerView 로 migration 하세요. (0) | 2017.04.13 |
[Android] Overview screen 을 꾸며보세요. (0) | 2017.04.11 |
댓글