Как наблюдать LiveData <PagedList>на андроид пейджинг в котлине - PullRequest
0 голосов
/ 17 октября 2019

Я не могу наблюдать за изменением активности LiveData<PagedList>, но пользовательский интерфейс обновляется (список увеличился в активности).

Я могу наблюдать его только один раз, когда инициализируются жизненные данные. когда библиотека подкачки вызывает метод loadAfter, пользовательский интерфейс обновляется, но не вызывает 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)

    }

DataSource.Factory в Android-пейджинге

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>
            ) {
            }

        }
    }
}

Модификация 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> изменением

Ответы [ 3 ]

0 голосов
/ 17 октября 2019

Вам нужно, чтобы ваш рабочий идентификатор был изменяемым, чтобы его можно было наблюдать при преобразовании. поэтому всякий раз, когда вы обновляете свою работу, 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)

... Представление переработчика будет обновлено. Ваше мнение о переработчике должно наследоваться от PagedListAdapter.

0 голосов
/ 18 октября 2019

После тестирования я знал, что список нельзя наблюдать, когда в нем есть внутренние данные, например add(), remove(). и т. д.

Его можно наблюдать только при изменении его ссылки, например, при операции создания или назначения:
list.value = null

Так что я не мог наблюдать изменение данных LiveData<List>

0 голосов
/ 17 октября 2019

Это происходит потому, что каждый раз, когда вы вызываете vm.listComment(workId), объект, который вы впервые связали в действии, уничтожается и создается новый объект.

Вы можете использовать Transformations с MediatorLiveData.

Активность:

 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...