AsyncQueryHandlerとは?
- 重いクエリをUIスレッド上でするとブロックされる場合があるため、非同期でクエリを実行するときに使用するクラス
- AsyncQueryHandlerでのクエリ実行は、AsyncQueryHandlerに内包されているHandlerThread上で行われます。
動機
- 参考するページが少ない
- 使おうと思ったら、ちょっと詰まった。
- 非同期処理の値を返すタイミングがずれてうまくデータがinsertされない事案が発生。
主なメソッド
メソッド名 | 概要 |
---|---|
startDelete(int token, Object cookie, Uri uri, String selection, String[] selectionArgs) | 非同期でdeleteを行う。 |
startInsert(int token, Object cookie, Uri uri, ContentValues initialValues) | 非同期でinsertを行う。 |
startQuery(int token, Object cookie, Uri uri, String[] projection, String selection, String[] selectionArgs, String orderBy) | 非同期でクエリを行う。 |
startUpdate(int token, Object cookie, Uri uri, ContentValues values, String selection, String[] selectionArgs) | 非同期でupdateを行う。 |
onDeleteComplete(int token, Object cookie, int result) | startDeleteメソッドが完了した時に呼び出される |
onInsertComplete(int token, Object cookie, Uri uri) | startInsertメソッドが完了した時に呼び出される |
onQueryComplete(int token, Object cookie, Cursor cursor) | startQueryメソッドが完了した時に呼び出される |
onUpdateComplete(int token, Object cookie, int result) | startUpdateメソッドが完了した時に呼び出される |
第1引数のtokenは処理を識別するために使用する値。
第2引数のcookieは完了時に渡すオブジェクト
完了時に呼ばれるメソッドの第3引数は各々対応するメソッドの戻り値
前提
- DB作成をContentProviderなどで行なっておく。
プログラム
AsyncQueryHandlerを継承したクラス
class CustomAsyncQueryHandler extends AsyncQueryHandler {
private static final String[] PROJECTION = new String[]{UserColumns.ID, UserColumns.NAME, UserColumns.EMAIL};
private final AsyncQueryHandlerActivity activity;
CustomAsyncQueryHandler(ContentResolver cr, AsyncQueryHandlerActivity activity) {
super(cr);
this.activity = activity;
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
activity,
android.R.layout.simple_list_item_2,
cursor,
PROJECTION,
new int[]{android.R.id.text1, android.R.id.text2});
activity.setListAdapter(adapter);
}
void insert(String name, String address) {
ContentValues value = new ContentValues();
value.put(UserColumns.NAME, name);
value.put(UserColumns.EMAIL, address);
startInsert(0, null, UserColumns.CONTENT_URI, value);
}
void delete() {
startDelete(0, null, UserColumns.CONTENT_URI, null, null);
}
void findAll() {
startQuery(0, null, UserColumns.CONTENT_URI, PROJECTION, null, null, null);
}
void findById(String where, String[] value) {
startQuery(0, null, UserColumns.CONTENT_URI, PROJECTION, where, value, null);
}
}
Activity
public class HogeHogeActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomAsyncQueryHandler asyncQueryHandler = new CustomAsyncQueryHandler(getContentResolver(), this);
// Delete
asyncQueryHandler.delete();
// Insert
for (int i = 1; i <= 50; i++) {
asyncQueryHandler.insert(UserColumns.NAME + i, UserColumns.EMAIL + i);
}
// Select
asyncQueryHandler.findAll();
}
}
おそらくもっといい方法があると思いますが、これがそのときの解決法でした。
参考
https://developer.android.com/reference/android/content/AsyncQueryHandler.html
http://shop.oreilly.com/product/0636920029397.do