androidx.paging.DataSource.Factory 时 Room 不检索数据(使用 LiveData + Kotlin Coroutines)

Posted

技术标签:

【中文标题】androidx.paging.DataSource.Factory 时 Room 不检索数据(使用 LiveData + Kotlin Coroutines)【英文标题】:Room not retrieve data when androidx.paging.DataSource.Factory (using LiveData + Kotlin Coroutines) 【发布时间】:2019-07-23 15:09:42 【问题描述】:

我有一个AmbassadorDAO,它有一个getAll() : List<Ambassador>,可以正确返回大使列表。

问题出现在我重构现有代码时以使用 DataSource.Factory 对列表进行分页

这里是代码

演示模块

活动

class AmbassadorActivity : AppCompatActivity() 

    override fun onCreate(savedInstanceState: Bundle?) 
        ...

        val viewModel by viewModel<AmbassadorViewModel>()

        val adapter = AmbassadorAdapter(this)
        list_of_ambassadors.adapter = adapter

        viewModel.ambassadors.observe(this, Observer  adapter.submitList(it) )

        viewModel.listAmbassadors()

        ...
    

    ...

视图模型

class AmbassadorViewModel(
    ...,
    private val getAllAmbassadorInteractor: GetAllAmbassadorInteractor
) : ViewModel() 

    ...

    // not working
    private val _ambassadors = MutableLiveData<PagedList<Ambassador>>()

    // it's working
    //private val _ambassadors = MutableLiveData<List<Ambassador>>()

    ...

    // not working
    val ambassadors : LiveData<PagedList<Ambassador>>
        get() =  _ambassadors

    // it's working
    //val ambassadors : LiveData<List<Ambassador>>
    //    get() =  _ambassadors

    ...

    fun listAmbassadors() 
        viewModelScope.launch 
            try 
                ...

                // not working
                // the data not return anything
                // the livedata is notified with null
                val data = getAllAmbassadorInteractor.exec()
                _ambassadors.value = LivePagedListBuilder(data, 20).build().value

                // it's working
                //_ambassadors.value = getAllAmbassadorInteractor.exec()

             catch (e: Exception) 
                e.printStackTrace()
             finally 
                ...
            
        
    


域模块

PRESENTATION(我的用例界面)之间的边界

interface GetAllAmbassadorInteractor 

    //suspend fun exec() : List<Ambassador>
    suspend fun exec() : DataSource.Factory<Int, Ambassador>


用例实现

class GetAllAmbassadorInteractorImpl(
    private val repository: AmbassadorRepository
) : GetAllAmbassadorInteractor 

    override suspend fun exec() = withContext(Dispatchers.IO)  repository.getAll() 


DATA(我的存储库接口)之间的边界

interface AmbassadorRepository 

    ...

    //suspend fun getAll() : List<Ambassador>
    suspend fun getAll() : DataSource.Factory<Int, Ambassador>

    ...


数据模块

存储库实施

class AmbassadorRepositoryImpl(
    private val ambassadorDAO: AmbassadorDAO
) : AmbassadorRepository 

    ...

    override suspend fun getAll() = ambassadorDAO.getAll().map  it.toDomain() 

    ...


我的 DAO

@Dao
interface AmbassadorDAO 

    ...

    @Query("SELECT * FROM $AmbassadorEntity.TABLE_NAME ORDER BY name DESC")
    fun getAll(): DataSource.Factory<Int, AmbassadorEntity>
    //fun getAll(): List<AmbassadorEntity>

    ...


我哪里做错了?

【问题讨论】:

【参考方案1】:

我猜你的错误在AmbassadorViewModel 类的这一行:

_ambassadors.value = LivePagedListBuilder(data, 20).build().value

代替那个用途:

_ambassadors.value = LivePagedListBuilder(data, 20).build()

也可以参考这个post,也许会有帮助。

【讨论】:

【参考方案2】:

在 Kotlin 扩展 (LifecycleScope) 的支持下,我们可以轻松地将 LiveData 与 Coroutine 连接起来,您无需使用 _ambassadors 等支持属性并将其设为 MutableLiveData。

androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha01 or higher.

这是一个使用协程并返回 LiveData 的函数

/**
 * Get all news rows livedata pageList from DB using Coroutine.
 */
suspend fun getAllNewsLiveData(): LiveData<PagedList<News>> 
    return withContext(Dispatchers.IO) 
        val data = mDao.getAllNews()
        LivePagedListBuilder(data, Constants.PAGINATION_SIZE).build()
    


现在在 UI 类中,我们可以简单地使用 lifescope 扩展来调用这个函数

  lifecycleScope.launchWhenStarted 
        newsViewModel.getNews()?.observe(this@NewsActivity, Observer  pagedNewsList -> pagedNewsList.let  newsAdapter.submitList(pagedNewsList)  )
    

【讨论】:

以上是关于androidx.paging.DataSource.Factory 时 Room 不检索数据(使用 LiveData + Kotlin Coroutines)的主要内容,如果未能解决你的问题,请参考以下文章