我正在尝试在我的应用程序中添加评论功能。就像Instagram或Facebook一样,在将评论成功保存到数据库后,它们会添加到评论列表中。我正在使用Android Architecture Components(ViewModel,LiveData和分页库)。
这是我的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
}}
如何正确执行?
CommentsDataFactory
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
}}
CommentsDataSource
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)
}
}}
答案 0 :(得分:-1)
做到这一点的正确方法是:
将新添加的注释发送到远程服务器(根据您的代码,您将从服务器获取所有注释)。
为此,您将调用一些ViewModel
方法,例如addComment()
。它将从您的apiClient
中调用某些方法。
在DataSource
上调用invalidate(即使在ViewModel
中也是如此,即使使用相同的addComment()
方法也是如此),它将触发您的PagedList
更新。
commentsDataSource.invalidate();