3

你知道如何让 Room DAO 返回 aLiveData<Cursor>吗?


我需要从我的数据库中请求很多对象。
由于内存问题,我买不起沉重的对象列表,我需要一个光标。
当然数据可以更新,我需要在它发生时得到通知。
所以 aLiveData<Cursor>应该是一个很好的解决方案。

但是,当我编译这个时:

@Dao
public interface FooDao {

    @Query("SELECT * FROM foo")
    LiveData<Cursor> getFoo();

}

Android Studio 对我说: Error:(22, 22) error: Not sure how to convert a Cursor to this method's return type

好吧...请不要告诉我我们无法通过光标获得数据更新通知:/

4

2 回答 2

2

感谢评论中的@pskink,这是我的解决方案:

public class DbLiveData<T>
        extends MutableLiveData<T> {

    public interface DataLoader<T> {

        T loadData();

    }

    @NonNull
    private final InvalidationTracker.Observer mDatabaseObserver;

    @NonNull
    private DataLoader<T> mDataLoader;

    @NonNull
    private final Executor mExecutor;

    public DbLiveData(@NonNull String[] tables, @NonNull Executor executor, @NonNull DataLoader<T> dataLoader) {
        mExecutor = executor;
        mDataLoader = dataLoader;
        mDatabaseObserver = new InvalidationTracker.Observer(tables) {
            @Override
            public void onInvalidated(@NonNull Set<String> tables) {
                loadData();
            }
        };
        loadData();
    }

    @Override
    protected void onActive() {
        super.onActive();
        DB.get() // I get my DB from a Service Locator
                .getInvalidationTracker()
                .addObserver(mDatabaseObserver);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        DB.get() // I get my DB from a Service Locator
                .getInvalidationTracker()
                .removeObserver(mDatabaseObserver);
    }

    private void loadData() {
        mExecutor.execute(
                () -> postValue(mDataLoader.loadData())
        );
    }

}

我创建了一个 LiveData 来管理一个InvalidationTracker.Observer. 您只需将一个传递DataLoader给构造函数,这个必须Cursor从数据库中获取。
像这样 :

new DbLiveData<Cursor>(
    new String[] { "foo" },
    getExecutor(), // Provide an Executor
    () -> DB.get() // I get my DB from a Service Locator
            .fooDao()
            .getFoo()
)
于 2017-08-18T12:30:10.670 回答
0

如果使用 Room 2.x,您可以使用 RoomDatabase 的实例

RoomDatabase appDatabase;
...

public LiveData<Cursor> getCursorLiveData(){
    return appDatabase.getInvalidationTracker().createLiveData(new String[]{"table1","table2"}, true, ()->{
       Cursor cursor = ...;
       return cursor;
    }
}

table1, table2 是要观察的表。如果您希望 computeFunction(last function arg) 将在事务中完成,请提供 true 作为第二个参数

于 2019-05-10T21:02:06.243 回答