如何使用分页库正确实现 kotlin 协程?

zed*_*abs 3 android kotlin

我有一个 android 应用程序,我想在其中实现 Kotlin Couroutines,我遇到的困惑是我在哪里使用协程。我有 viewModel 作为-

class PostViewModel : ViewModel() {

    var postPagedList: LiveData<PagedList<UnsplashImageDetails>>? = null
    private var postLiveDataSource: LiveData<PageKeyedDataSource<Int, UnsplashImageDetails>>? = null

    var popularPagedList: LiveData<PagedList<UnsplashImageDetails>>? = null
    private var popularLiveDataSource: LiveData<PageKeyedDataSource<Int, UnsplashImageDetails>>? = null

    init {
        val postDataSourceFactory = PostDataSourceFactory()
        val popularDataSourceFactory = PopularDataSourceFactory()

        postLiveDataSource = postDataSourceFactory.getPostLiveDataSource()
        popularLiveDataSource = popularDataSourceFactory.getPopularLiveDataSource()

        val config: PagedList.Config = (PagedList.Config.Builder()).setEnablePlaceholders(false)
            .setPageSize(PostDataSource().PAGE_SIZE).build()
        val configPop: PagedList.Config = (PagedList.Config.Builder()).setEnablePlaceholders(false)
            .setPageSize(PopularDataSource().PAGE_SIZE).build()

        postPagedList = LivePagedListBuilder(postDataSourceFactory, config).build()
        popularPagedList = LivePagedListBuilder(popularDataSourceFactory, configPop).build()
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该在哪里使用异步方法,在此活动中或在我通过改造获取数据的存储库类中。

cor*_*her 7

在这种情况下,协程应该在PostDataSource. 如果您想知道是否应该GlobalScope在那里使用,答案是否定的。有一种更优雅的方法可以做到这一点。您还应该找到一种取消作业的方法来防止内存泄漏。这就是我在这里写这篇文章的原因,它解决了这个特定的问题。

你应该找到一种方法来管理你的协程ViewModel,但你应该在DataSource.

最好的方法来做到这一点。

创建数据类:

data class Listing<T>(
    val pagedList: LiveData<PagedList<T>>,
    val networkState: LiveData<NetworkState>, //initial state
    val refreshState: LiveData<NetworkState>, // second state, after first data loaded
    val refresh: () -> Unit, // signal the data source to stop loading, and notify its callback
    val retry: () -> Unit,  // remake the call
    val clearCoroutineJobs: () -> Unit // the way to stop jobs from running since no lifecycle provided )

enum class Status {
    RUNNING,
    SUCCESS,
    FAILED
}

@Suppress("DataClassPrivateConstructor")
data class NetworkState private constructor(
    val status: Status,
    val msg: String? = null
) {
    companion object {
        val LOADED =
            NetworkState(Status.SUCCESS)
        val LOADING =
            NetworkState(Status.RUNNING)

        fun error(msg: String?) = NetworkState(
            Status.FAILED,
            msg
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您的数据源工厂应该是这样的

您从这种方法中受益的是,您可以在以下onCleared方法中取消作业ViewModel

override fun onCleared() {
        super.onCleared()
        //finish the coroutines opened jobs
        listing.clearCoroutineJobs.invoke()
    }
Run Code Online (Sandbox Code Playgroud)

请注意,这也是 Igit 在此github repo 中提供的指南。

我确实同意解决方案应该更简单,但是如果您考虑一下,协程和并发总体上与简单性无关,您在这里处理的是线程。