Android Paging库异常:LivePagedList返回空列表且未通知观察者
我帮你梳理下代码里可能导致观察者收不到数据通知的几个关键问题,以及对应的修复方案:
1. 回调线程错误:在主线程调用callback.onResult
Paging库要求ItemKeyedDataSource的加载回调(loadInitial/loadAfter里的callback.onResult)必须在执行加载操作的同一个线程调用——也就是你通过setFetchExecutor设置的后台线程。但你的代码里用observeOn(AndroidSchedulers.mainThread())把回调切换到了主线程执行,这会导致PagedList无法正确处理数据更新,进而无法触发LiveData的通知。
修复方案:
移除observeOn(AndroidSchedulers.mainThread()),让回调在subscribeOn指定的IO线程执行。Paging库会自动负责把PagedList的更新同步到主线程,供LiveData观察者接收:
// loadInitial 中的修改 compositeDisposable.add( MyService.getService().fetchData(queryMap) .subscribeOn(Schedulers.io()) // 移除这一行:.observeOn(AndroidSchedulers.mainThread()) .subscribeWith(object : DisposableObserver<OrdersResponse>() { override fun onNext(orders: OrdersResponse) { callback.onResult(orders.data) } override fun onError(e: Throwable) { e.printStackTrace() } override fun onComplete() { } }) ) // loadAfter 同理移除 observeOn 代码
2. DataSource.Factory 实现不规范
从ViewModel代码看,你直接把MyDatasource(params)传入了MyDataFactory,如果MyDataFactory是直接持有这个DataSource实例而非每次create()时生成新实例,会导致后续加载复用旧的DataSource,出现状态混乱。
正确的MyDataFactory实现:
class MyDataFactory(private val queryMap: HashMap<String, String>) : DataSource.Factory<String, Order>() { // 传入queryMap的副本,避免并发修改问题 private val safeQueryMap = HashMap(queryMap) override fun create(): DataSource<String, Order> { return MyDatasource(safeQueryMap) } }
ViewModel中调用方式保持不变即可。
3. ViewModel中dataList的赋值逻辑问题
你的dataList是var类型,每次调用getOrders()都会生成新的LiveData<PagedList<Order>>。如果Activity已经观察了旧的dataList,新实例的更新不会被旧观察者接收到。
优化方案:
改成嵌套的LiveData,支持多次调用getOrders()时自动切换数据源:
class MyViewModel() : ViewModel() { private var myPagingConfig: PagedList.Config? = null val dataList = MutableLiveData<LiveData<PagedList<Order>>>() fun getOrders(params: HashMap<String, String>) { if (myPagingConfig == null) { myPagingConfig = PagedList.Config.Builder() .setPageSize(LIMIT) .setPrefetchDistance(10) .setEnablePlaceholders(false) .build() } val newDataList = LivePagedListBuilder(MyDataFactory(params), myPagingConfig!!) .setInitialLoadKey(null) .setFetchExecutor(Executors.newFixedThreadPool(5)) .build() dataList.value = newDataList } }
Activity中观察方式调整为:
viewModel.dataList.observe(this) { pagedListLiveData -> pagedListLiveData.observe(this) { orders -> // 处理数据更新 } }
4. 潜在内存泄漏问题:CompositeDisposable未清理
你的MyDatasource使用了CompositeDisposable,但没有在DataSource销毁时清理订阅。建议添加invalidate重写方法:
override fun invalidate() { super.invalidate() compositeDisposable.dispose() }
把这些问题修复后,应该就能解决观察者收不到数据更新的问题了。
内容的提问来源于stack exchange,提问作者Ana Koridze

