使用 ItemKeyedDataSource 观察房间数据库 table 中的变化

Observing changes in Room Database table using ItemKeyedDataSource

我已经实现了 class,它扩展了 ItemKeyedDataSource 并提供来自房间数据库的数据访问对象 (DAO) 的分页数据。我的 DAO 的查询方法将数据对象列表(未被 LiveData 包装)传递给 DataSource 回调。

包装数据库 table 中发生更改后,例如如果更改来自后台服务,建议使用什么方法使 DataSource 失效? DataSource.Factory<Integer, T> return DAOs 可以生成的参数中如何实现自动数据失效?

自动 DataSource 失效可以通过挂钩 InvalidationTracker.ObserverInvalidationTracker 来实现。 您可以从 getInvalidationTracker() 获取 InvalidationTracker 个实例。

我的 InvalidationTracker.Observer 是这样实现的:

public class DataSourceTableObserver extends InvalidationTracker.Observer {

    private DataSource dataSource;

    public DataSourceTableObserver(@NonNull String tableName) {
        super(tableName);
    }

    @Override
    public void onInvalidated(@NonNull Set<String> tables) {
       if (dataSource != null) dataSource.invalidate();
    }

    public void setCurrentDataSource(DataSource source) {
        dataSource = source;
    }

}

我在内心 DataSource.Factory class 中这样使用它:

public static class Factory implements DataSource.Factory<TvProgram, TvProgram> {

    private Context appContext;
    private DataSourceTableObserver observer;
    private InvalidationTracker tracker;
    private int channelId;

    public Factory(Context context, int channelId) {
        appContext = context.getApplicationContext();

        observer = new DataSourceTableObserver(AppDatabase.PROGRAMS_TABLE);
        tracker = AppDatabase.getInstance(appContext).getInvalidationTracker();
        tracker.addObserver(observer);

        this.channelId = channelId;
    }

    @Override
    public DataSource<TvProgram, TvProgram> create() {
        EpgDataSource epgDataSource = new EpgDataSource(appContext, channelId);
        observer.setCurrentDataSource(epgDataSource);
        return epgDataSource;
    }

    public void cleanUp() {
        tracker.removeObserver(observer);
        observer = null;
    }

}

DataSourceTableObserver 使 DataSource 无效时,Factory 内部 class 使用最新数据创建新的 DataSource 实例。