观察未使用 LiveData<PagedList> 调用

Observe not called with LiveData<PagedList>

我正在通过 Room 数据库使用 PagedList 体系结构组件,但无法将结果返回到观察方法。

Here is my Dao:

@Dao
interface WorkPackageStorageDao {

    @Query("SELECT * from workpackages where id = :id")
    fun getById(id: String): Workpackage

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(workpackage: Workpackage)

    @Query("Select * from workpackages WHERE id LIKE '%' || :searchString || '%' order by :orderBy")
    fun searchWorkpackages(searchString : String, orderBy : String) : DataSource.Factory<Int, Workpackage>

    @Query("SELECT * FROM workpackages")
    fun searchWorkPackgesTest() : List<Workpackage>

    @Query("Select * from workpackages WHERE id LIKE '%' || :searchString || '%' order by :orderBy")
    fun searchWorkPackgesTestQuery(searchString : String, orderBy : String) : List<Workpackage>

    @Query("DELETE from workpackages")
    fun deleteAll()

}

My repository:

fun getAllWorkPackagesTestQuery() : List<Workpackage> {
    return workpackagesDao.searchWorkPackgesTestQuery("",SortedBy.WorkPackageNumber.type)
}

fun getAllWorkPackages() : DataSource.Factory<Int, Workpackage> {
    return getSortedAndSearchedWorkPackages("",
        SortedBy.WorkPackageNumber
    )
}

fun getSortedAndSearchedWorkPackages(searchString : String, sortBy: SortedBy) : DataSource.Factory<Int, Workpackage> {
    return workpackagesDao.searchWorkpackages(searchString,sortBy.type)
}

Here is the method in my view model:

suspend fun fetchWorkPackagesInitial(
    workWeek: Configurations.AppWeek,
    pagingLimit: Int
) {

    coroutineScope {
        withContext(Dispatchers.IO) {
            val factory: DataSource.Factory<Int, Workpackage> =
                workPackageRepository.getAllWorkPackages()

            val pagedListBuilder =
                LivePagedListBuilder<Int, Workpackage>(factory, pagingLimit)
            workPackagesList = pagedListBuilder.build() 
            val list = workPackageRepository.getAllWorkPackagesTestQuery() //27 Items returned, query is fine. 
        }

    }
}

Here is my fragment:

    mainViewModel.week.observe(this, Observer {
        it ?: return@Observer

        launch { workPackagesViewModel.fetchWorkPackagesInitial(it, PAGING_LIMIT) }

    })

    //Observe never called.  
    workPackagesViewModel.workPackagesList?.observe(this, Observer { wpList ->
        wpList ?: return@Observer

        adapter = WorkPackagesRecyclerAdapter(this)
        adapter.submitList(wpList)
        binding.workPackagesRecyclerView.adapter = adapter
        adapter.notifyDataSetChanged()

    })

作为对我的查询的测试,我实施了:

val list = workPackageRepository.getAllWorkPackagesTestQuery() 

其中returns27条,查询正常。我是否设置了 Dao 错误,LivePagedListBuilder 错误?为什么不调用 observe?

您没有收到物品,因为它是 PagedList。需要触发加载才能获取页面

这就是为什么通过 submitList 将 PagedList 提供给 PagedListAdapter 最终会加载数据。

当您使用 PagedListAdapter 时,您也不需要手动调用 adapter.notifyDataSetChanged(),因为 DiffUtil 会在内部处理它。


但是,您绝对应该在 UI 线程 (Dispatcher.MAIN) 上检索 DataSource.FactoryLivePagedListBuilder 以及 PagedList,因为线程由 Paging 库的 Room 集成在内部处理。观察(并在未加载的元素上调用 getItem()将触发加载,加载将由开箱即用的 DataSource 异步执行。



Paging的使用方法是这样的:

class MyViewModel(
    private val workPackageStorageDao: WorkPackageStorageDao
): ViewModel() {
    private val searchQuery: MutableLiveData<String> = MutableLiveData("")

    val workPackages: LiveData<PagedList<WorkPackage>> = Transformations.switchMap(searchQuery) { searchText ->
        val factory = workPackageStorageDao.searchWorkPackages(searchText, SortedBy.WorkPackageNumber)
        val pagedListBuilder = LivePagedListBuilder<Int, WorkPackage>(factory, pagingLimit)
        pagedListBuilder.build()
    }
}

然后在片段中:

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    // ... setup RecyclerView, etc

    viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java, viewModelFactory)
    viewModel.workPackages.observe(viewLifecycleOwner, Observer { pagedList ->
        adapter.submitList(pagedList)
    })
}

在适配器中:

class MyAdapter: PagedListAdapter<WorkPackage, MyAdapter.ViewHolder>(WorkPackage.ITEM_CALLBACK) {
     override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
         val workPackage = getItem(position)
         if(workPackage != null) {
             holder.bind(workPackage)
         }
     }
}

长话短说,这里不需要协程。使用 Paging Library 和 LiveData,它将在正确的线程上加载。