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)的主要内容,如果未能解决你的问题,请参考以下文章