¿Cómo observar los datos de PagedList?
Estoy usando Paging Library y Android Architecture Components. Simplemente quiero observar livedata de pagedlist y actualizar mi RecyclerView cuando hay un cambio.
Estoy observando objects isLoadingLiveData, isEmptyLiveData y errorLiveData que son objects MediatorLiveData creados en mi ViewModel y observados en mi fragment. Y también observando resultLiveData que devuelve la list Gist captada desde el control remoto.
- Sala: error al utilizar @Transaction
- Rx Java Retrofit con flatMap se ejecuta solo una vez
- Kotlin - ¿Cómo importar packages de nodos?
- Métodos de acceso fuera del object complementario - Kotlin
- Duplicación del adaptador en la Vista de reciclador
En mi ViewModel, creé un PagedList LiveData y cada vez que cambian los datos, quería actualizar isLoadingLiveData, isEmptyLiveData, errorLiveData y PagedListAdapter . Por lo tanto, definí isLoadingLiveData, isEmptyLiveData, errorLiveData y resultLiveData como objects MediatorLiveData. Agregué resultLiveData como fuente de estos objects. Entonces cuando resultLiveData ha cambiado, se invocarán los methods onChanged de estos objects. Y resultLiveData depende de userNameLiveData, por lo que cuando userNameLiveData ha cambiado, se llamará a allGistsLiveData y obtendrá los datos. Por ejemplo, cuando el usuario desliza la list, estoy configurando userNameLiveData y haciendo una llamada de networking nuevamente.
Mi ViewModel:
private val userNameLiveData = MutableLiveData<String>() private var gists: LiveData<PagedList<Gist>>? = null val allGistsLiveData: LiveData<PagedList<Gist>> get() { if (null == gists) { gists = GistModel(NetManager(getApplication()), getApplication()).getYourGists(userNameLiveData.value!!).create(0, PagedList.Config.Builder() .setPageSize(PAGED_LIST_PAGE_SIZE) .setInitialLoadSizeHint(PAGED_LIST_PAGE_SIZE) .setEnablePlaceholders(PAGED_LIST_ENABLE_PLACEHOLDERS) .build()) } return gists!! } val resultLiveData = MediatorLiveData<LiveData<PagedList<Gist>>>().apply { this.addSource(userNameLiveData) { gists = null this.value = allGistsLiveData } } val isLoadingLiveData = MediatorLiveData<Boolean>().apply { this.addSource(resultLiveData) { this.value = false } } val isEmptyLiveData = MediatorLiveData<Boolean>().apply { this.addSource(resultLiveData) { this.value = false } } val errorLiveData = MediatorLiveData<Boolean>().apply { this.addSource(resultLiveData) { if (it == null) { this.value = true } } } fun setUserName(userName: String) { userNameLiveData.value = userName }
y mi fragment:
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.isEmptyLiveData.observe(this@YourGistsFragment, Observer<Boolean> { isVisible -> emptyView.visibility = if (isVisible!!) View.VISIBLE else View.GONE }) viewModel.isLoadingLiveData.observe(this@YourGistsFragment, Observer<Boolean> { it?.let { swipeRefreshLayout.isRefreshing = it } }) viewModel.errorLiveData.observe(this@YourGistsFragment, Observer<Boolean> { it?.let { showSnackBar(context.getString(R.string.unknown_error)) } }) viewModel.setUserName("melomg") viewModel.resultLiveData.observe(this@YourGistsFragment, Observer { it -> gistAdapter.setList(it?.value) }) } override fun onRefresh() { viewModel.setUserName("melomg") }
mi repository
fun getYourGists(userName: String): LivePagedListProvider<Int, Gist> { return remoteDataSource.getYourGists(userName, GitHubApi.getGitHubService(context)) }
mi remoteDataSource:
fun getYourGists(username: String, dataProvider: GitHubService): LivePagedListProvider<Int, Gist> { return object : LivePagedListProvider<Int, Gist>() { override fun createDataSource(): GistTiledRemoteDataSource<Gist> = object : GistTiledRemoteDataSource<Gist>(username, dataProvider) { override fun convertToItems(items: ArrayList<Gist>?): ArrayList<Gist>? { return items } } } }
Traté de crear esta solución a partir de este proyecto . Pero mi problema es resultLiveData ha estado cambiando sin esperar la respuesta de llamada de networking y, por lo tanto, el resultado de la respuesta se ha ignorado y mi interfaz de usuario se está actualizando antes de que los datos hayan llegado. Dado que resultLiveData está cambiando antes de la request y, por lo tanto, todavía no hay datos. ¿Simplemente cómo puedo observar livedata pagedlist?
- Android: ¿Cómo llamar a la function ndk de Kotlin?
- Cuál es el enfoque correcto cuando la function de Kotlin no toma el tipo de nullable
- Firebase Firestre Android no puede deserializar el object
- ¿TreeWalker no está trabajando con Kotlin / Gradle?
- ¿Las classs de Kotlin que henetworkingan de las classs de Java también henetworkingan de Cualquiera?
- Kotlin Annotation IntDef
- ¿Cómo orderar basado en / comparar múltiples valores en Kotlin?
- reproducir cualquier video embedded en la vista web en Android con intención
Finalmente, encontré una solución funcional, pero no creo que sea la mejor. Entonces, si tiene alguna idea, no dude en responder. Aquí está mi solución:
Dejé de envolver mis datos de PagedList con MediatorLiveData . Todavía dejo mi rest de datos en vivo ( isLoadingLiveData, isEmptyLiveData, errorLiveData
) como MediatorLiveData
pero agregué su fuente cuando mi idea inicial, PagedList LiveData, se inicializó. Aquí está el código:
private var gists: LiveData<PagedList<Gist>>? = null private val userNameLiveData = MutableLiveData<String>() val isLoadingLiveData = MediatorLiveData<Boolean>() val isEmptyLiveData = MediatorLiveData<Boolean>() val errorLiveData = MediatorLiveData<ErrorMessage>() val allGistsLiveData: LiveData<PagedList<Gist>> get() { if (gists == null) { gists = GistModel(NetManager(getApplication()), getApplication()).getYourGists(userNameLiveData.value!!).create(0, PagedList.Config.Builder() .setPageSize(Constants.PAGED_LIST_PAGE_SIZE) .setInitialLoadSizeHint(Constants.PAGED_LIST_PAGE_SIZE) .setEnablePlaceholders(Constants.PAGED_LIST_ENABLE_PLACEHOLDERS) .build()) isLoadingLiveData.addSource(gists) { isLoadingLiveData.value = false } isEmptyLiveData.addSource(gists) { if (it?.size == 0) { isEmptyLiveData.value = true } } errorLiveData.addSource(gists) { if (it == null) { errorLiveData.value = ErrorMessage(errorCode = ErrorCode.GENERAL_ERROR) } } } } return gists!! } fun setUserName(userName: String) { isLoadingLiveData.value = true userNameLiveData.value = userName gists = null allGistsLiveData }
- No se esperan arguments de tipo para la diversión findViewById (p0: Int): Ver
- Se esperaba un valor de tipo Booleano: menu emergente