检索结果的List包装
在BDFlow库中提供了FlowCursorList
和FlowQueryList
两个容器类,可用于容纳检索结果。它们提供与List相同的方法使你能简单地将其用于BaseAdapter
或其他List<? extends Model>
可用的地方。
FlowCursorList
FlowCursorList
是一个只读的用于缓存的容器,它包含的方法很类似与BaseAdapter
比如getCount()
和getItem(position)
方法(但并没有继承BaseAdapter和List)
对于我们需要在屏幕上显示大量数据但实际只需要载入显示部分的数据时,这个容器非常有用。它虽然像是CursorAdapter
但并不继承任何Adapter类,但提供了与数据库数据检索、转换的方便的API接口。
这里是定义它的一些方式:
使用任意的查询语句初始化它,像是
From
、StringQuery
和Where
// 第一个参数指定是否开启缓存 new FlowCursorList<>(true, SQLite.select().from(TestModel.class) .where(TestModel1_Table.name.like("pasta%"))); // 开启缓存并指定缓存大小(当缓存不可用时忽略) new FlowCursorList<>(1000, SQLite.select().from(TestModel.class) .where(TestModel1_Table.name.like("pasta%")));
对特定类和列条件进行检索
new FlowCursorList<>(true, TestModel.class, TestModel1_Table.name.like("pasta%")); new FlowCursorList<>(1000, TestModel.class, TestModel1_Table.name.like("pasta%"));
示例
private class TestModelAdapter extends BaseAdapter {
private FlowCursorList<TestModel1> mFlowCursorList;
public TestModelAdapter() {
// retrieve and cache rows that have a name like pasta%
mFlowCursorList = new FlowCursorList<>(true, TestModel.class,
TestModel1_Table.name.like("pasta%"));
}
@Override
public int getCount() {
return mFlowCursorList.getCount();
}
@Override
public TestModel1 getItem(int position) {
return mFlowCursorList.getItem(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Implement here
}
}
自定义缓存
可以通过重写getBackingCache()
方法来替换默认的LruCache
缓存方式:
FlowCursorList<TestModel> list = new FlowCursorList<TestModel>(true, someWhere) {
@Override
protected ModelCache<TestModel, ?> getBackingCache() {
return new SparseArrayBasedCache();
}
}
FlowQueryList
FlowQueryList
:
- 实现了java的
List
接口 - 所有对表的修改都是实时的
- 默认情况下所有的修改都是即时的
- 如果你不希望这些修改操作在主线程中进行,请设置
flowTableList.setTransact(true)
- Internally its backed by a
FlowCursorList
to include all of it's existing functionality.
好的实践
不要在循环中进行大量的单一操作,因为每个操作都会调用
refresh()
方法刷新数据库。推荐的做法是使用事务包裹这些操作:FlowQueryList<TableModel> flowQueryList = ...; // DON'T for (int i = 0; i < 50; i++) { TableModel object = anotherList.get(i); flowQueryList.remove(object); } // better flowQueryList.beginTransaction(); for (int i = 0; i < 50; i++) { TableModel object = anotherList.get(i); flowQueryList.remove(object); } flowQueryList.endTransactionAndNotify(); // DO flowQueryList.removeAll(anotherList);
在其他地方对数据进行了修改后,
FlowQueryList
内的数据会不一致,有两种方式刷新数据:- 调用
refresh()
方法手动刷新数据 - 开启自动刷新:
flowQueryList.enableSelfRefreshes(context);
- 调用
如果你进行了大量的更改同时对这些事件都注册了监听,好的方式是使用
endTransactionAndNotify()
方法将通知在最后统一发送。flowQueryList.beginTransaction(); // perform model changes!! // calls any listeners associated with it (including the listener we registered earlier) // refreshes the list here (if registered) flowQueryList.endTransactionAndNotify();
示例
FlowQueryList<TestModel1> flowQueryList = new FlowQueryList<TestModel1>(TestModel1.class);
flowQueryList.beginTransaction();
// Deletes from the table and returns the item
TestModel1 model1 = flowQueryList.remove(0);
// Saves the item back into the DB, updates if it already exists
flowQueryList.add(model1);
// Updates the item in the DB
flowQueryList.set(model1);
// Clears the whole table
flowQueryList.clear();
flowQueryList.endTransactionAndNotify();