I have implemented class which extends ItemKeyedDataSource and provides paging data from room database's data access object (DAO). My DAO's query methods pass lists of data objects (not wrapped by LiveData
) to DataSource
callbacks.
What is the recommended way to invalidate DataSource
after changes occur in it's wrapped database table, for example if changes come from background Service? How automatic data invalidation is implemented in DataSource.Factory<Integer, T>
return parameter that DAOs can generate?
Automatic DataSource
invalidation can be implemented by hooking InvalidationTracker.Observer
to InvalidationTracker
.
You can get InvalidationTracker
instance from getInvalidationTracker().
I implemented my InvalidationTracker.Observer
like this:
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;
}
}
And I'm using it in my inner DataSource.Factory
class like this:
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;
}
}
When DataSourceTableObserver
invalidates DataSource
, it's Factory
inner class creates new DataSource
instance with newest data.