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

Efficient Android Threading #11 AsyncQueryHandler 를 이용한 콘텐트 프로바이더 접근

by 돼지왕왕돼지 2018. 3. 27.

Efficient Android Threading #11 AsyncQueryHandler 를 이용한 콘텐트 프로바이더 접근


이 글은 Efficient Android Threading 의 일부 내용만 발췌한 내용입니다.

자세한 내용은 책을 구입해서 보세용.


asyncqueryhandler, Callback, CancellationSignal, canceloperation, concurrent access, Content Provider, contentprovider, contentprovideroperation, contentresolver, Cookie, cp, cp 구현, crud, cursorloader, db 병렬 처리, Efficient Android Threading #11 AsyncQueryHandler 를 이용한 콘텐트 프로바이더 접근, Enable, enableWriteAheadLogging, memory 소비, merge, multiple connection, onDeleteComplete, onInsertComplete, onQueryComplete, onUpdateComplete, request type, result callback, sqlite db, startDelete, startInsert, startQuery, startUpdate, token, UI Thread, write-ahead logging, 낮은 처리량, 다수 트랜잭션, 동시 db 접근, 동시 읽기 트랜잭션, 동시 처리량, 동일 스레드, 바인더 스레드, 복사본, 순차적, 쓰기, 유틸 클래스, 콘텐트 프로바이더, 콘텐트 프로바이더의 백그라운드 처리에 대한 정당성, 콜백, 한계

13.1. 콘텐트 프로바이더에 대한 간략한 소개


-

AsyncQueryHandler 는 ContentProvider 에서 비동기적 CRUD 작업 처리를 전문으로 하는 유틸 클래스이다.

작업은 별도 스레드에서 실행되고, 결과가 사용 가능할 때는 콜백이 시작하는 스레드에서 호출된다.

AsyncQueryHandler 클래스는 UI 스레드에서 CP 로 작업을 떠넘기는데 사용되고, UI 스레드는 백그라운드 태스크가 완료되면 결과를 수신한다.





13.2. 콘텐트 프로바이더의 백그라운드 처리에 대한 정당성


-

CP 는 데이터에 접근하는 클라이언트의 개수 또는 얼마나 많은 클라이언트를 동시에 처리할 수 있는지 제어할 수 없다.

프로바이더의 캡슐화된 데이터는 데이터 세트를 읽거나 쓰는 여러 스레드로부터 동시에 접근될 수 있다.

따라서 프로바이더가 스레드 안전하지 않으면 프로바이더에 대한 동시 접근이 데이터 불일치로 이어질 수 있다.



-

SQLite DB 는 기본적으로 순차적이다.

이는 낮은 처리량으로 이어질 수 있다.

동시 처리량을 높이기 위해 데이터베이스는 명시적으로 활성화할 수 있는 미리 쓰기 로깅(Write-Ahead Loggin) 이라는 기술을 제공한다.

db.enableWriteAheadLogging();


이 기능이 활성화되면 여러 읽기가 데이터 불일치를 일으킬 수 없으므로, DB 는 병렬로 다수의 트랙잭션을 처리할 수 있고, 동시적으로 DB 에 접근하는 동시 읽기 트랜잭션을 허용한다.

미리 쓰기 로깅은 읽기/쓰기 트랙잭션이 같은 데이터 세트에서 동시에 발생하지 않도록 보장한다.

즉, 쓰기는 활성화된 읽기 트랜잭션이 있을 때 원본 DB 에 기록되지 않고 데이터베이스의 복사본에 수행되고, 복사본이 원본에 순간적으로 merge 된다.


https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#enableWriteAheadLogging()


Reference 문서에 따르면 concurrent access 를 지원하는 경우 이 녀석을 enable 하는 것은 성능상의 이점을 가져오지만,

Multiple connection 을 열기 때문에 disable 상태에 비해 꽤 많은 메모리를 더 소비한다.



-

동일한 앱 프로세스의 구성요소에서 호출이 시작되면, CP 구현은 ContentResolver 의 호출자와 동일한 스레드에서 호출된다.

그러나 CP 가 다른 프로세스에서 호출되면 CP 구현은 바인더 스레드에서 대신 호출된다.



-

안드로이드 플랫폼에는 프로바이더를 위한 두 가지 특별한 메커니즘인 AsyncQueryHandler 와 CursorLoader 가 포함되어 있다.





13.3. AsyncQueryHandler 사용


-

AsyncQueryHandler 는 ContentResolver, 백그라운드 실행, 스레드 간 메시지 전달 처리를 간소화해주는 추상 클래스이다.

AsyncQueryHandler 는 ContentResolver 의 프로바이더 동작을 래핑하는 네 가지 메서드를 포함한다.

final void startDelete(int token, Object cookie, Uri uri, String selection, String[] selectionArgs)

final void startInsert(int token, Object cookie, Uri uri, ContentValues initialValues)

final void startQuery(int token, Object cookie, Uri uri, String[] projection, String selection, String[] selectionArgs, String orderBy)

final void startUpdate(int token, Object cookie, Uri uri, ContentValues values, String selection, String[] selectionArgs)


위 함수들을 호출하면 백그라운드 스레드에서 요청을 실행하고, 동작이 완료되면 AsyncQueryHandler 의 콜백으로 결과를 반환한다.

콜백은 요청을 수행한 스레드에서 불린다.



-

다음의 Callback 을 override 해서 사용하면 된다.

protected void onDeleteComplete(int token, Object cookie, int result)

protected void onUpdateComplete(int token, Object cookie, int result)

protected void onInsertComplete(int token, Object cookie, Uri result)

protected void onQueryComplete(int token, Object cookie, Cursor result)



-

token 은 request type 을 지정한다.

cancelOperation(token)을 통해 해당 요청을 취소할 수도 있다.


cookie 는 요청에 대한 부가정보이다.

별다른 역할은 없이 result callback 에 함께 반환된다.




** 13.3.1. 예제 : 연락처 확장 리스트




** 13.3.2. AsyncQueryHandler 이해


-

프로바이더 요청이 호출되면, 요청을 담은 메시지가 하나의 백그라운드 스레드에 의해 처리되기 위해 메시지 큐에 추가된다.

백그라운드 스레드 처리는 앱 전역적이다.

asyncqueryhandler, Callback, CancellationSignal, canceloperation, concurrent access, Content Provider, contentprovider, contentprovideroperation, contentresolver, Cookie, cp, cp 구현, crud, cursorloader, db 병렬 처리, Efficient Android Threading #11 AsyncQueryHandler 를 이용한 콘텐트 프로바이더 접근, Enable, enableWriteAheadLogging, memory 소비, merge, multiple connection, onDeleteComplete, onInsertComplete, onQueryComplete, onUpdateComplete, request type, result callback, sqlite db, startDelete, startInsert, startQuery, startUpdate, token, UI Thread, write-ahead logging, 낮은 처리량, 다수 트랜잭션, 동시 db 접근, 동시 읽기 트랜잭션, 동시 처리량, 동일 스레드, 바인더 스레드, 복사본, 순차적, 쓰기, 유틸 클래스, 콘텐트 프로바이더, 콘텐트 프로바이더의 백그라운드 처리에 대한 정당성, 콜백, 한계



** 13.3.3. 한계


-

API Level 5 에 프로바이더 일괄 작업을 지원하기 위해 ContentProviderOperation 이 추가됐다.

큰 데이터 세트에 대한 여러 트랜잭션을 피하기 위해 하나의 트랙잭션에 원자적으로 실행될 수 있는 삽입 세트를 지원한다.



-

API Level 16 에 CancellationSignal  이 추가되었다.

이를 사용하면 ContentResolver 쿼리를 취소할 수 있지만, AsyncQueryHandler 를 지원하지 않으므로 여전히 cancelOperation(token) 만을 사용해야 한다.







댓글0