2

我正在使用 aContentProvider来查询数据库并返回 aCursor中使用的 a 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, ...); 
    }

    ...
}

项目内容提供者:

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,Nexus 7

4

2 回答 2

5

移动设备并非旨在处理这些数据量。

但是,如果您真的想给可怜的用户施加如此大的滚动列表,您可以将其设计为仅按需加载条目的虚拟列表;请参阅Android 无尽列表

注意:使用OFFSET子句是低效的;有关详细信息,请参阅滚动光标

于 2012-12-05T20:57:02.380 回答
2

I agree with CL that you shouldn't do this. This isn't a good idea on mobile and neither is it on desktops. Who wants to scroll 30000 elements? What for? Most probably the user is looking for one result only, isn't she? So provide an easy way to filter the result set.

Until the result set is small enough to be actually usable (this is not the same as the list scrolling fine - it's probably a much smaller number of results) you simply should display the total number of hits for the current query and maybe some elements as a sample to the user. The user must filter the list to get to actually usable sizes.

于 2012-12-06T16:54:40.350 回答