を使用しContentProvider
てデータベースをクエリし、Cursor
で使用される を返しCursorLoader
ます。
アイテム活動:
public class ItemsActivity extends SherlockActivity implements LoaderCallbacks<Cursor> {
@Override
public void onCreate(Bundle savedInstance) {
....
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
...
}
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
return new CursorLoader(getApplicationContext(), itemsListUri, ...);
}
...
}
ItemsContentProvider:
public Cursor query(Uri uri, String[] projection, String selection, ...) {
SqliteQueryBuilder builder = new SqliteQueryBuilder();
builder.setTables(ItemsTable.NAME);
return builder.query(db, projection, selection, ...);
}
アクティビティには がありListView
、CursorAdapter
( を介して更新されたLoaderCallbacks
) を使用してカーソル内のデータを表しています。
大規模なデータ セット (たとえば、30,000 行を超える) 内のアイテムを検索する必要があるまで、これは正常に機能しています。ログを観察すると、ルックアップがメモリ制限を超えており、結果のカーソルからいくつかの行が削除されていることがわかります。
私の質問: このようなカーソルを使用する場合、非常に大きなデータセットを処理する最良の方法は何ですか?
私の現在の解決策は、SQLiteクエリContentProvider
をオフセットと制限のある一連のクエリに分割し、MergeCursor
クラスを使用してこれらのクエリを結合することです:
private static final int LIMIT = 5000;
// Ignoring projection, selection, etc for simplicity here
public Cursor query(Uri uri, String projection, String selection, ...) {
List<Cursor> cursors = newList();
int offset = 0;
Cursor c = db.rawQuery("select * from items limit " + LIMIT + " offset " + offset, null);
while (c.getCount() > 0) {
cursors.add(c);
offset += c.getCount();
c = db.rawQuery("select * from items limit " + LIMIT + " offset " + offset, null);
}
return createMergedCursor(cursors);
}
private Cursor createMergedCursors(List<Cursor> cursors) {
if (cursors.size() == 1) {
return cursors.get(0);
}
return new MergeCursor(toCursorsArray(cursors));
}
これによりすべてのデータが読み込まれますが、最初のルックアップの実行中に長い遅延が発生します。複数のクエリが実行されている間、リスト ビューは約 5 秒間空になります。
単一のルックアップ (バッチ ルックアップではなく) を試すと、ロードはほぼ瞬時に行われることに注意してください。
そう:
単一のクエリを使用する: リスト ビューの更新は高速ですが、スクロールが一時停止し、メモリの制限に達します。
バッチ クエリの使用: リスト ビューの更新は遅くなりますが、スクロールはスムーズで、メモリ制限に達しません。
リストビューをすばやく更新するだけでなく、リストをスクロールするときに必要に応じてより多くのデータを取得するより良いソリューションがあるかどうか疑問に思っています。
アンドロイド 4.2.1、ネクサス 7