2

を使用し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, ...);
}

アクティビティには がありListViewCursorAdapter( を介して更新された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

4

2 に答える 2

5

モバイル デバイスは、これらの量のデータを処理するようには設計されていません。

ただし、貧弱なユーザーにこのような大きなスクロール リストを強制したい場合は、エントリがオンデマンドでのみ読み込まれる仮想リストとして設計できます。Android エンドレス リストを参照してください。

注:OFFSET節を使用するのは非効率的です。詳細については、スクロール カーソルを参照してください。

于 2012-12-05T20:57:02.380 に答える
2

私はあなたがこれをすべきではないというCLに同意します。これはモバイルではお勧めできませんし、デスクトップでもお勧めできません。30000要素をスクロールしたいのは誰ですか?何のために?おそらく、ユーザーは1つの結果だけを探していますね。したがって、結果セットをフィルタリングする簡単な方法を提供します。

結果セットが実際に使用できるほど小さくなるまで(これは、リストが細かくスクロールするのと同じではありません。おそらく結果の数がはるかに少ないでしょう)、現在のクエリのヒットの総数と、場合によってはいくつかの要素を次のように表示する必要があります。ユーザーへのサンプル。ユーザーは、実際に使用可能なサイズに到達するためにリストをフィルタリングする必要があります。

于 2012-12-06T16:54:40.350 に答える