android - 如何观察PagedList数据?

标签 android kotlin android-architecture-components android-livedata android-viewmodel

我正在使用Paging Library和Android体系结构组件。我只是想观察pagedlist livedata并在发生更改时更新RecyclerView。

我正在观察isLoadingLiveData,isEmptyLiveData和errorLiveData对象,它们是在ViewModel中创建并在片段中观察到的MediatorLiveData对象。并观察resultLiveData,它从远程返回获取的Gist列表。

在我的ViewModel中,我创建了一个PagedList LiveData,并且每当数据更改时,我都想更新isLoadingLiveData,isEmptyLiveData,errorLiveData和PagedListAdapter。因此,我将isLoadingLiveData,isEmptyLiveData,errorLiveData和resultLiveData定义为MediatorLiveData对象。我添加了resultLiveData作为这些对象的源。因此,当resultLiveData更改时,将调用这些对象的onChanged方法。并且resultLiveData依赖于userNameLiveData,因此,当userNameLiveData更改时,将调用allGistsLiveData并将其获取数据。例如,当用户滑动列表时,我正在设置userNameLiveData并再次进行网络通话。

我的ViewModel:

private val userNameLiveData = MutableLiveData<String>()
private var gists: LiveData<PagedList<Gist>>? = null

val allGistsLiveData: LiveData<PagedList<Gist>>
    get() {
        if (null == gists) {
            gists = GistModel(NetManager(getApplication()), getApplication()).getYourGists(userNameLiveData.value!!).create(0,
                    PagedList.Config.Builder()
                            .setPageSize(PAGED_LIST_PAGE_SIZE)
                            .setInitialLoadSizeHint(PAGED_LIST_PAGE_SIZE)
                            .setEnablePlaceholders(PAGED_LIST_ENABLE_PLACEHOLDERS)
                            .build())
        }
        return gists!!
    }

val resultLiveData = MediatorLiveData<LiveData<PagedList<Gist>>>().apply {
    this.addSource(userNameLiveData) {
        gists = null
        this.value = allGistsLiveData
    }
}


val isLoadingLiveData = MediatorLiveData<Boolean>().apply {
    this.addSource(resultLiveData) { this.value = false }
}

val isEmptyLiveData = MediatorLiveData<Boolean>().apply {
    this.addSource(resultLiveData) { this.value = false }
}

val errorLiveData = MediatorLiveData<Boolean>().apply {
    this.addSource(resultLiveData) {
        if (it == null) {
            this.value = true
        }
    }
}

fun setUserName(userName: String) {
    userNameLiveData.value = userName
}

和我的片段:
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    viewModel.isEmptyLiveData.observe(this@YourGistsFragment, Observer<Boolean> { isVisible ->
        emptyView.visibility = if (isVisible!!) View.VISIBLE else View.GONE
    })

    viewModel.isLoadingLiveData.observe(this@YourGistsFragment, Observer<Boolean> {
        it?.let {
            swipeRefreshLayout.isRefreshing = it
        }
    })

    viewModel.errorLiveData.observe(this@YourGistsFragment, Observer<Boolean> {
        it?.let {
            showSnackBar(context.getString(R.string.unknown_error))
        }
    })

    viewModel.setUserName("melomg")
    viewModel.resultLiveData.observe(this@YourGistsFragment, Observer { it -> gistAdapter.setList(it?.value) })
}


override fun onRefresh() {
    viewModel.setUserName("melomg")
}

我的资料库:
fun getYourGists(userName: String): LivePagedListProvider<Int, Gist> {
    return remoteDataSource.getYourGists(userName, GitHubApi.getGitHubService(context))
}

我的remoteDataSource:
fun getYourGists(username: String, dataProvider: GitHubService): LivePagedListProvider<Int, Gist> {
    return object : LivePagedListProvider<Int, Gist>() {
        override fun createDataSource(): GistTiledRemoteDataSource<Gist> = object : GistTiledRemoteDataSource<Gist>(username, dataProvider) {
            override fun convertToItems(items: ArrayList<Gist>?): ArrayList<Gist>? {
                return items
            }
        }
    }
}

我试图从this project创建此解决方案。但是我的问题是
resultLiveData一直在更改,而无需等待网络 call 响应,因此响应结果被忽略,并且在数据到达之前更新了我的ui。由于resultLiveData在请求前发生更改,因此尚无数据。简而言之,我如何观察分页列表实时数据?

最佳答案

最后,我找到了一个可行的解决方案,但我认为这不是最佳解决方案。因此,如果您有任何想法,请随时回答。这是我的解决方案:

我放弃了用PagedList包装MediatorLiveData数据。我仍将所有其他实时数据(isLoadingLiveData, isEmptyLiveData, errorLiveData)保留为MediatorLiveData,但是在我的要点PagedList LiveData初始化时添加了它们的源。这是代码:

private var gists: LiveData<PagedList<Gist>>? = null
private val userNameLiveData = MutableLiveData<String>()
val isLoadingLiveData = MediatorLiveData<Boolean>()
val isEmptyLiveData = MediatorLiveData<Boolean>()
val errorLiveData = MediatorLiveData<ErrorMessage>()

val allGistsLiveData: LiveData<PagedList<Gist>>
    get() {
        if (gists == null) {
                gists = GistModel(NetManager(getApplication()), getApplication()).getYourGists(userNameLiveData.value!!).create(0,
                        PagedList.Config.Builder()
                                .setPageSize(Constants.PAGED_LIST_PAGE_SIZE)
                                .setInitialLoadSizeHint(Constants.PAGED_LIST_PAGE_SIZE)
                                .setEnablePlaceholders(Constants.PAGED_LIST_ENABLE_PLACEHOLDERS)
                                .build())


                isLoadingLiveData.addSource(gists) { isLoadingLiveData.value = false }
                isEmptyLiveData.addSource(gists) {
                    if (it?.size == 0) {
                        isEmptyLiveData.value = true
                    }
                }
                errorLiveData.addSource(gists) {
                    if (it == null) {
                        errorLiveData.value = ErrorMessage(errorCode = ErrorCode.GENERAL_ERROR)
                    }
                }
            }
        }
        return gists!!
    }


fun setUserName(userName: String) {
    isLoadingLiveData.value = true
    userNameLiveData.value = userName
    gists = null
    allGistsLiveData
}

关于android - 如何观察PagedList数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47130006/

相关文章:

java - 如何加减小时和分钟

android - 如何使用 Material 设计来挑选时间?

kotlin - 如何使用委托(delegate) 'by' 在 Kotlin 中获取对委托(delegate)实例的引用?

java - 使用 Architecture Components MVVM 进行身份验证,将 token 从 Repository 传递到 ViewModel

android - 如何更改导航 Controller 中目的地的标签属性?

android - 是否可以使用 ViewPager 制作此 Android 屏幕动画?

android - 检查 ListView 内的 EditText 对象中的条目

android - 将图像 URI 传递给另一个 Activity

operators - 箭头 ("->") 运算符在 Kotlin 中的作用是什么?