LoginSignup
2
1

More than 5 years have passed since last update.

重いクエリを非同期で行うには

Last updated at Posted at 2017-11-02

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

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1