观察未通过LiveData <PagedList>调用

时间:2019-10-11 12:40:55

标签: android datasource android-architecture-components android-livedata pagedlist

我正在使用Room数据库使用PagedList体系结构组件,但无法将结果返回给watch方法。

  

这是我的道:

@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()

}
  

我的存储库:

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)
}
  

这是我的视图模型中的方法:

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. 
        }

    }
}
  

这是我的片段:

    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() 

它返回27个项目,所以查询很好。我设置的Dao错误,LivePagedListBuilder错误吗?为什么不叫观察?

1 个答案:

答案 0 :(得分:1)

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

这就是为什么通过PagedListAdapter将PagedList赋予submitList会最终加载数据的原因。

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


但是,您绝对应该在UI线程(DataSource.Factory)上检索LivePagedListBuilderPagedList以及Dispatcher.MAIN,因为线程是由分页库的内部集成房间。观察(并在已卸载的元素上调用getItem()将触发加载,并且DataSource可以立即执行加载。



使用分页的方法如下:

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)
         }
     }
}

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