AsyncTaskLoader の使い方 (7/8) 〜 データベースと CursorLoader

AsyncTaskLoader___Android_Developers

AsyncTaskLoader | Android Developers


目次

1. Thread と AsyncTask
2. AsyncTaskLoader の利点
3. LoaderManager の利用
4. よくある間違いと回避法
5. 基本的な Loader の実装
6. いろいろな Loader の使用例
7. データベースと CursorLoader
8. Loader の弱点を克服する


7. データベースと CursorLoader

CursorLoader は ContentProviders 照会専用のローダです

結果としてデータベースカーソルを返す。

AsyncTaskLoaderを継承したバックグランドスレッドでデータベースクエリーを実行します。

Acitivityのライフサイクルに応じて、Activity.startManagingCursor(Cursor c) やカーソルのライフサイクルの管理を置き換えます。
→ close() は呼ばない。

データベースを監視し、データが変更された新しいカーソルを返します。
→ requery() は呼ばない。

ListFragment内 CursorAdapterでの使い方

@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    return new BookmarksLoader(getActivity(), 
        args.getDouble("latitude"), args.getDouble("longitude")); 
}

@Override 
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 
    adapter.swapCursor(data); 
    // The list should now be shown. 
    if (isResumed()) { 
        setListShown(true); 
    } else { 
        setListShownNoAnimation(true); 
    } 
}

@Override 
public void onLoaderReset(Loader<Cursor> loader) { 
    adapter.swapCursor(null); 
}

ContentProvider の複雑さを必要としない場合 SimpleCursorLoader。

例えば、ローカルのデータベースにアクセスしたい場合。

SimpleCursorLoader はすべての ContentProvider 特有のものを取り除いている CursorLoader に基づく抽象クラスです。
ただ実際のデータベースクエリを実行する1つのメソッドをオーバーライドする必要があります。

ブックマークの例

private static class BookmarksLoader extends SimpleCursorLoader { 

    private double latitude; 
    private double longitude; 

    public BookmarksLoader(Context context, double latitude, double longitude) { 
        super(context); 
        this.latitude = latitude; 
        this.longitude = longitude; 
    }

    @Override 
    protected Cursor getCursor() { 
        return DatabaseManager.getInstance().getBookmarks(latitude, longitude); 
    } 
}

public class DatabaseManager { 
    private static final Uri URI_BOOKMARKS = Uri.parse("sqlite://your.package.name/bookmarks"); 
    ... 
    public Cursor getBookmarks(double latitude, double longitude) { 
        // A big database query you don't want to see 
        ... 
        cursor.setNotificationUri(context.getContentResolver(), URI_BOOKMARKS); 
        return cursor; 
    } 
    ...

    public boolean addBookmark(Bookmark bookmark) { 
        SQLiteDatabase db = helper.getWritableDatabase(); 
        db.beginTransaction(); 
        try {
            // Other database stuff you don't want to see 
            ... 
            long result = db.insert(DatabaseHelper.BOOKMARKS_TABLE_NAME, null, values); 
            db.setTransactionSuccessful(); 
            // Will return -1 if the bookmark was already present 
            return result != -1L; 
        } finally { 
            db.endTransaction(); 
            context.getContentResolver().notifyChange(URI_BOOKMARKS, null); 
        } 
    } 
}

(→ 「8. Loader の弱点を克服する」につづく)


関連ワード:  Android初心者開発