Estoy haciendo una aplicación que obtiene la (pseudo) los valores de latencia haciendo una petición a alguna de las direcciones url y la grabación de cuánto tiempo va a tomar.
En primer lugar, yo uso posterior para obtener una respuesta JSON desde un servidor web. Esta respuesta contiene: el nombre del host (por ejemplo, Ebay reino unido), la dirección url del host (por ejemplo, www.ebay.co.uk), y la url de una imagen. Yo mapa esta respuesta en mi clase de datos que se parece a la siguiente:
data class(
val name: String,
var url: String,
val icon: String,
var averagePing: Long = -1
)
el url es un var de la propiedad como antes de hacer las llamadas para obtener los valores de latencia, necesito agregar https:// en el fin de realizar la solicitud.
Estoy haciendo todo esto así:
fun getHostsLiveData() {
viewModelScope.launch(Dispatchers.IO) {
val hostList = repo.getHosts()
for (host in hostList) {
host.url = "https://" + host.url
host.averagePing = -1
}
hostListLiveData.postValue(hostList)//updated the recyclerview with initial values
//with default (-1) value of averagePing
for (host in hostList) {
async { pingHostAndUpdate(host.url, hostList) }
}
}
}
El primer bucle for prepara mis datos. La línea después de que el bucle for presenta los datos para el reciclador adaptador, con el fin de mostrar el nombre de host, la dirección url y el icono de inmediato (funciona esto decir que tengo un trabajo observador de la LiveData), mientras que la estoy esperando los valores de latencia.
El segundo bucle for se llama a la función para calcular la latencia de valores para cada host y el updateHostList() la función de las actualizaciones de la LiveData.
Esta es la forma en que las funciones mira:
suspend fun pingHostAndUpdate(url: String, hostList: MutableList<Host>) {
try {
val before = Calendar.getInstance().timeInMillis
val connection = URL(url).openConnection() as HttpURLConnection //Need error handling
connection.connectTimeout = 5*1000
connection.connect()
val after = Calendar.getInstance().timeInMillis
connection.disconnect()
val diff = after - before
updateHostList(url, diff, hostList)
} catch (e: MalformedURLException) {
Log.e("MalformedURLExceptionTAG", "MalformedURLException")
} catch (e: IOException) {
Log.e("IOExceptionTAG", "IOException")
}
}
fun updateHostList(url: String, pingResult: Long, hostList: MutableList<Host>) {
//All this on mainThread
var foundHost: Host? = null
var index = 0
for (host in hostListLiveData.value!!) {
if (host.url == url) {
foundHost = host
break
}
index++
}
if (foundHost != null) {
viewModelScope.launch(Dispatchers.Main) {
val host = Host(foundHost.name, foundHost.url, foundHost.icon, pingResult)
Log.d("TAAAG", "$host")
hostList[index] = host
hostListLiveData.value = hostList
}
}
}
Todo esto sucede en el viewModel. Actualmente estoy actualizando mi lista por presentar la lista completa de nuevo cuando yo cambio una propiedad de un elemento de la lista, que parece horrible para mí.
Mi pregunta es: ¿Cómo puedo actualizar a una propiedad de host y tener que actualizar la interfaz de usuario de forma automática?
Gracias de antemano
Edit: Mi observador se parece a esto:
viewModel.hostListLiveData.observe(this, Observer { adapter.updateData(it) })
Y updateData() se parece a esto:
fun updateData(freshHostList: List<Host>) {
hostList.clear()
hostList.addAll(freshHostList)
notifyDataSetChanged()
}
@ArpitShukla, ¿sugieren yo tendría 2 funciones de actualización? para mostrar la lista inicial y otro para actualizar el elemento de la lista? O acabo de poner tanto notifyDataSetChanged() y notifyItemChanged() en updateData()?
Edit2: se ha cambiado mi llamada a la función para hacerlo de forma asincrónica.