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

How to add Item in PagedList of Paging Library

我正在尝试在我的应用程序中添加评论功能。就像 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. 调用一些方法
  3. 在您的 DataSource 上调用 invalidate(也在 ViewModel 中,即使是在相同的 addComment() 方法中),它会触发您的 PagedList更新。

    commentsDataSource.invalidate();