我使用ContentProvider查询数据库并返回CursorLoader中使用的Cursor:
ItemsActivity:
public class ItemsActivity extends SherlockActivity implements LoaderCallbacks {
@Override
public void onCreate(Bundle savedInstance) {
....
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
...
}
@Override
public Loader 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行).观察日志我发现查找超出了内存限制,并且从结果游标中删除了一些行.
我的问题:在使用这样的游标时,处理非常大的数据集的最佳方法是什么?
我目前的解决方案是将ContentProvider中的SQLite查询拆分为具有偏移和限制的一系列查询,然后使用MergeCursor类组合这些查询:
private static final int LIMIT = 5000;
// Ignoring projection, selection, etc for simplicity here
public Cursor query(Uri uri, String projection, String selection, ...) {
List 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 cursors) {
if (cursors.size() == 1) {
return cursors.get(0);
}
return new MergeCursor(toCursorsArray(cursors));
}
这将加载所有数据,但是第一次执行查找时会有很长的延迟.执行多个查询时,列表视图为空约5秒钟.
请注意,当我尝试单个查找(而不是批量查找)时,加载几乎是即时的,尽管在达到内存限制时滚动列表时会有轻微的暂停.
所以:
使用单个查询:快速列表视图更新,但滚动暂停和内存限制已达到.
使用批处理查询:慢速列表视图更新,但滚动顺畅且没有达到内存限制.
我想知道是否有更好的解决方案可以快速更新列表视图,但是在滚动列表时也会根据需要获取更多数据.
Android 4.2.1,Nexus 7