尽管下一个会回答我自己的问题,但对于数据可能发生变异的数据库-网络逻辑,这个解决方案还不够,因为它不处理已保存在数据库中的数据的更新。
请原谅抽象类的数量 - 我通常为扩展和可重用性工作。此外,还请原谅 Java 和 Kotlin 代码的混合。由于某种原因,某些库在我使用 Kotlin 的项目中无法识别,但在这些情况下可以随意使用 Kotlin。
所以基本上我们需要创建一个新的DataSource 类
abstract class MyDataSource<Value>: PositionalDataSource<Value>() {
override fun loadInitial(params: PositionalDataSource.LoadInitialParams, callback: PositionalDataSource.LoadInitialCallback<Value>) {
callback.onResult(getDataFromDatabase(params.requestedLoadSize, params.requestedStartPosition)?: listOf(), 0)
}
override fun loadRange(params: PositionalDataSource.LoadRangeParams, callback: PositionalDataSource.LoadRangeCallback<Value>) {
callback.onResult(getDataFromDatabase(params.loadSize, params.startPosition)?: listOf())
}
abstract fun getDataFromDatabase(limit: Int, offset: Int): List<Value>?
}
实现的Concert数据类:
class ConcertDataSource : MyDataSource<Concert>() {
override fun getDataFromDatabase(limit: Int, offset: Int): List<Concert>? {
return ConcertAA.getConcerts(limit, offset)
}
}
然后我们需要一个 DataSourceFactory 来创建我们的 DataSource 实例:
abstract class MyDataSourceFactory<Key, Value> : DataSource.Factory<Key, Value>() {
val mutableLiveData: MutableLiveData<DataSource<Key, Value>>? = null
override fun create(): DataSource<Key, Value> {
val dataSource = createDataSource()
mutableLiveData?.postValue(dataSource)
return dataSource
}
abstract fun createDataSource(): DataSource<Key, Value>
}
以及为 ConcertDataSource 实现的 DataSourceFactory:
class ConcertDataSourceFactory : MyDataSourceFactory<Int, Concert>() {
override fun createDataSource(): DataSource<Int, Concert> {
return ConcertDataSource()
}
}
然后是ViewModel 的PagedList,它将拥有我们的数据源:
public class ConcertViewModel extends ViewModel {
public final LiveData<PagedList<Concert>> concertList;
private FetchCallback callback;
private final int pageSize = 10
PagedList.BoundaryCallback<Concert> boundaryCallback = new PagedList.BoundaryCallback<Concert>(){
boolean frontLoaded =false;
public void onZeroItemsLoaded() {
// callback.fetch(...);
}
public void onItemAtFrontLoaded(@NonNull Concert itemAtFront) {
if(!frontLoaded) {
// callback.fetch(...);
}
frontLoaded = true;
}
public void onItemAtEndLoaded(@NonNull Concert itemAtEnd) {
// callback.fetch(...);
}
};
public ConcertViewModel(FetchCallback callback) {
this.callback = callback;
ConcertDataSourceFactory dataSourceFactory = new ConcertDataSourceFactory();
PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(pageSize)
.setInitialLoadSizeHint(pageSize)
.setEnablePlaceholders(false)
.build();
concertList = new LivePagedListBuilder<>(dataSourceFactory, config).setBoundaryCallback(boundaryCallback).build();
}
public void refresh() {
conertList.getValue().getDataSource().invalidate();
}
}
我们使用BoundaryCallback 来侦听当 PagedList 需要加载更多时,只要它到达列表的任一侧并且我们的数据库数据没有存储任何额外数据。这将能够从服务器(或任何数据提供者)获取更多数据。使用自定义回调调用 fetch:
interface FetchCallback{
fun fetch(limit: Int?, concertIdOffset: String?)
}
现在,由于我们需要将回调传递给ViewModel,我们需要告诉ViewModelProviders 如何使用参数创建ViewModel 的新实例。这是使用ViewModelProvider.Factory:
abstract class MyViewModelFactory(
private val callback: FetchCallback) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return createViewModel(callback)
}
abstract fun <T : ViewModel> createViewModel(callback: FetchCallback): T
}
我们为 Concert 实现的ViewModelFactory:
class ConcertViewModelFactory(callback: FetchCallback) : MyViewModelFactory(callback) {
override fun <T : ViewModel> createViewModel(callback: FetchCallback): T {
return ConcertViewModel(callback) as T
}
}
最后,我们从我们的视角初始化ViewModel(Activity、Fragment等):
val factory = ConcertViewModelFactory(
object: FetchCallback{
override fun fetch(limit: Int?, eventIdOffset: String?, level: RequestParameters.RequestLevel, showLoader: Boolean) {
//Do the call to the server
}
})
viewModel = ViewModelProviders.of(this, factory).get(ConcertViewModel::class.java)
adapter = ConcertAdapter()
viewModel.concertList.observe(viewLifecycleOwner, Observer(adapter::submitList))
这将是我的问题的答案,但是,请注意(至少目前)Android 分页库不处理可变数据。例如,如果音乐会有一个可以更改的乐队列表(例如,其中一个乐队无法参加音乐会),则该逻辑无法更新保存在数据库中的数据,因为它只在执行时向服务器请求额外的数据。到达存储在数据库中的数据的任一边界(顶部或底部)。因此,出于我自己的目的,这个库是无用的。