如何观察LiveData 在Kotlin中使用Android分页进行观察

问题描述 投票:0回答:3

我无法观察到LiveData<PagedList>活动的变化,但是UI已更新(活动列表已增加)。

我只能在实时数据初始化时观察一次。当分页库调用loadAfter方法时,ui会更新,但未调用pageList.observe {}

[首先,我将数据请求过程放入Kotlin协程中,我无法观察到数据的变化,然后我使用了异步请求。它仍然无法正常工作。

这是我的代码:

PlayActivity主要代码


private val commentAdapter =
        object : BasePagedAdapter(diffCallback, this) {
            // just bind recycleview item and corresponding view model. etc.
        }

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_play)
        binding.vm = vm
        binding.lifecycleOwner = this

        val workId = intent.getLongExtra(WORK_ID, 0)

        vm.listComment(workId)

        play_rv_comment.adapter = commentAdapter

        /* herer is the problem*/
        vm.commentList.observe(this, Observer {
            /*only log once when called loadInitial*/
            LogUtils.e("observe", it)
            commentAdapter.submitList(it)
        })


PlayViewModel

class PlayViewModel : BaseViewModel() {

    var workId: Long = 0
    // the data which I want to observe
    lateinit var commentList: LiveData<PagedList<WorkComment>>

    private val commentPageSize = 15

    fun listComment(workId: Long) {
        // init by DataSource.Factory in android paging library
        commentList = BaseDataSourceFactory(workId).toLiveData(commentPageSize)

    }

Android分页中的DataSource.Factory

class BaseDataSourceFactory(
    val workId: Long
) :
    DataSource.Factory<Long, WorkComment>() {

    override fun create(): DataSource<Long, WorkComment> {
        return object : PageKeyedDataSource<Long, WorkComment>() {
            override fun loadInitial(
                params: LoadInitialParams<Long>,
                callback: LoadInitialCallback<Long, WorkComment>
            ) {
                try {
                    val res = RetrofitUtil.getInstanceWithJwt().create(WorkCommentApi::class.java)
                        .listComment(
                            workId, 1, params.requestedLoadSize
                        )
                    res.enqueue(object : retrofit2.Callback<TResult> {
                        override fun onFailure(call: Call<TResult>, t: Throwable) {
                        }

                        override fun onResponse(call: Call<TResult>, response: Response<TResult>) {
                            callback.onResult(
                                response.body()!!.toList(WorkComment::class.java),
                                null, 2)
                        }
                    })
                } catch (e: SocketTimeoutException) {
                    ToastUtils.showShort("请稍候重试")
                } catch (e: Exception) {
                    LogUtils.e(e.localizedMessage)
                }

            }

            // called many times, but I can't observe the PagedList change
            override fun loadAfter(
                params: LoadParams<Long>,
                callback: LoadCallback<Long, WorkComment>
            ) {
                val res = RetrofitUtil.getInstanceWithJwt().create(WorkCommentApi::class.java)
                    .listComment(
                        workId, 1, params.requestedLoadSize
                    )
                res.enqueue(object : retrofit2.Callback<TResult> {
                    override fun onFailure(call: Call<TResult>, t: Throwable) {
                    }

                    override fun onResponse(call: Call<TResult>, response: Response<TResult>) {
                        callback.onResult(
                            response.body()!!.toList(WorkComment::class.java),
                            params.key + 1
                        )
                    }
                })
            }

            override fun loadBefore(
                params: LoadParams<Long>,
                callback: LoadCallback<Long, WorkComment>
            ) {
            }

        }
    }
}

Retrofit Api

interface WorkCommentApi {

    /**
     * list comment
     */
    @GET("public/work/comment")
    fun listComment(@Query("workId") workId: Long, @Query("current") current: Long, @Query("size") size: Int): Call<TResult>
}

我想知道应该怎么做才能观察LiveData<PagedList>的变化

android kotlin retrofit2 android-livedata android-paging
3个回答
0
投票

之所以如此,是因为每次调用vm.listComment(workId)时,您首先绑定到活动中的对象都会被杀死,并会创建新对象。

您可以将TransformationsMediatorLiveData一起使用。

活动:

 viewModel.logout().observe(this, Observer { 
// do here
})

ViewModel:


class RepackViewModel(app: Application) : BaseViewModel(app) {

// IMPORTANT - Mediator
    val logout = MediatorLiveData<PagedList<WorkComment>>()
    fun logout() : LiveData<PagedList<WorkComment>> = logout
   init {
// IMPORTANT - passes repo update to activity 
       logout.addSource(repo.getLogoutResponse()) { logout.postValue(it) }
  }
}

存储库:

class BaseRepository(val app: Application) {

    private val logout = MutableLiveData<PagedList<WorkComment>>()

    fun getLogoutResponse(): LiveData<PagedList<WorkComment>> = logout

   override fun create(): DataSource<Long, WorkComment> {
  //when you get your data
   logout.value = // your value
}

0
投票

您需要使您的工作ID为可变数据,以便转换进行观察。因此,每当您更新作品ID时,它都会获取评论。像这样...

ViewModel:

val workIdMutableLiveData: MutableLiveData<Int> = MutableLiveData(workId)

//This performs the meat of the work to display the items in the recyclerview
var commentsList = Transformations.switchMap(workIdMutableLiveData) { workId ->
    val config = PagedList.Config.Builder()
        .setEnablePlaceholders(false)
        .setPageSize(pagingLimit)
        .build()
    val pagedListBuilder = LivePagedListBuilder<Long, WorkComment>(BaseDataSourceFactory(workId), config)
    pagedListBuilder.build()
}

然后在您的活动中,观察

    yourViewModel.commentsList.observe(this, Observer { list ->
        list ?: return@Observer

        adapter.submitList(list)
        yourRecyclerView.adapter = adapter
    })

[每当您通过执行操作更新workIdMutableLiveData时

workIdMutableLiveData.postValue(workId)

... recyclerview将更新。您的recyclerview必须继承自PagedListAdapter。


0
投票

[经过测试,我知道列表在进行内部数据更改时无法观察到,例如add()remove()。等等

仅在更改其引用后才能观察到,例如创建或分配操作:list.value = null

所以我看不到LiveData<List>的数据变化

© www.soinside.com 2019 - 2024. All rights reserved.