android - 如何在分页库的PagedList中添加Item

标签 android kotlin android-architecture-components android-paging

我正在尝试在我的应用程序中添加评论功能。就像 Instagram 或 Facebook 一样,评论成功保存到数据库后将添加到评论列表中。我正在使用 Android Architecture Components (ViewModel、LiveData 和 Paging 库)。

这是我的 ViewModel,我认为我应该在其中更新我的 PagedList

class CommentsViewModel : ViewModel() {
lateinit var networkState: LiveData<NetworkState>
private val executor: Executor
private lateinit var tDataSource: LiveData<CommentsDataSource>
private lateinit var dataFactory: CommentsDataFactory
private var repository: CommentsRepository
private var commentsList: LiveData<PagedList<Comment>>? = null

init {
    executor = Executors.newFixedThreadPool(5)
    repository = CommentsRepository()
}

fun getComments(postId: Int): LiveData<PagedList<Comment>>? {
    dataFactory = CommentsDataFactory(executor, postId)

    tDataSource = dataFactory.mutableLiveData

    networkState = Transformations.switchMap(dataFactory.mutableLiveData) {
        it.networkState
    }

    val pagedListConfig = PagedList.Config.Builder()
            .setEnablePlaceholders(true)
            .setInitialLoadSizeHint(Constants.INITIAL_LOAD)
            .setPageSize(Constants.PAGE_SIZE)
            .build()

    commentsList = LivePagedListBuilder(dataFactory, pagedListConfig)
            .setFetchExecutor(executor)
            .build()
    return commentsList
}

//This method here brings errors.
fun addComment(comment: Comment) {
    commentsList?.value?.add(comment)
}

fun postComment(map: Map<String, String>): LiveData<NetworkState> {
    repository.postComment(map)
    return repository.mNetworkState
}}

如何正确地做到这一点?

评论数据工厂

class CommentsDataFactory(private val executor: Executor, private val postId: Int)
: DataSource.Factory<Int, Comment>() {

val mutableLiveData = MutableLiveData<CommentsDataSource>()

override fun create(): DataSource<Int, Comment>? {
    val dataSource = CommentsDataSource(executor, postId)
    mutableLiveData.postValue(dataSource)
    return dataSource
}}

评论数据源

class CommentsDataSource(private val retryExecutor: Executor, private val post_id: Int)
: PageKeyedDataSource<Int, Comment>() {

private var retry: (() -> Any)? = null
private val apiClient = getClient()

val networkState = MutableLiveData<NetworkState>()

val initialLoad = MutableLiveData<NetworkState>()

fun retryAllFailed() {
    val prevRetry = retry
    retry = null
    prevRetry?.let {
        retryExecutor.execute {
            it.invoke()
        }
    }
}

override fun loadBefore(
        params: LoadParams<Int>,
        callback: LoadCallback<Int, Comment>) {
}

override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Comment>) {
    networkState.postValue(NetworkState.LOADING)
    apiClient.getComments(post_id, params.key).enqueue(
            object : retrofit2.Callback<List<Comment>> {
                override fun onFailure(call: Call<List<Comment>>, t: Throwable) {
                    retry = {
                        loadAfter(params, callback)
                    }
                    networkState.postValue(NetworkState.error(t.message ?: "unknown err"))
                }

                override fun onResponse(
                        call: Call<List<Comment>>,
                        response: Response<List<Comment>>) {
                    when {
                        response.isSuccessful -> {
                            retry = null
                            callback.onResult(response.body() as MutableList<Comment>, params.key + 10)
                            networkState.postValue(NetworkState.LOADED)
                        }
                        response.code() == 404 -> networkState.postValue(NetworkState.END)
                        else -> {
                            retry = {
                                loadAfter(params, callback)
                            }
                            networkState.postValue(
                                    NetworkState.error("error code: ${response.code()}"))
                        }
                    }
                }
            }
    )
}

override fun loadInitial(
        params: LoadInitialParams<Int>,
        callback: LoadInitialCallback<Int, Comment>) {

    val request = apiClient.getComments(post_id, 0)

    networkState.postValue(NetworkState.LOADING)
    initialLoad.postValue(NetworkState.LOADING)

    try {
        retry = null
        val response = request.execute()

        when {
            response.isSuccessful -> {
                networkState.postValue(NetworkState.LOADED)
                initialLoad.postValue(NetworkState.LOADED)
                callback.onResult(response.body() as MutableList<Comment>, 0, 10)
            }
            response.code() == 404 -> networkState.postValue(NetworkState.END)
            else -> networkState.postValue(
                    NetworkState.error("error code: ${response.code()}"))
        }

    } catch (ioException: IOException) {
        retry = {
            loadInitial(params, callback)
        }
        val error = NetworkState.error(ioException.message ?: "unknown error")
        networkState.postValue(error)
        initialLoad.postValue(error)
    }
}}

最佳答案

正确的做法是:

  1. 将您新添加的评论发送到您的远程服务器(根据您的代码,您正在从服务器获取所有评论)。 为此,您将调用一些 ViewModel 方法,例如 addComment()。这将从您的 apiClient 调用一些方法。

  2. 调用invalidate在您的 DataSource 上(也在 ViewModel 中,甚至在相同的 addComment() 方法中),它会触发您的 PagedList 更新。

    commentsDataSource.invalidate();
    

关于android - 如何在分页库的PagedList中添加Item,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53060795/

相关文章:

java - 如何知道一个点是否在android中的多边形内部

java - 升级android studio后"Failed to resolve: support-v4"

kotlin - Kotlin函数重载(varargs与单个参数)

android - 具有多个 ViewModel 的 Activity

android - 在 AndroidViewModel 中初始化 LiveData

android - 带有上下文的存储库模块实现

java - Mockito 抛出 java.lang.NoClassDefFoundError 和 java.lang.VerifyError

多次调用 Android LiveData observe

kotlin - 如何在kotlin中声明一个可为空的函数参数

android - Clean Architecture 和 Paging 3.0 with Room