Voi face o aplicație care devine (pseudo) valorile timpilor de latență de a face o cerere la unele url-uri și înregistrare cât timp va dura.
În primul rând, eu folosesc de reabilitare pentru a obține un răspuns JSON de la un server web. Acest răspuns conține: numele de gazdă (de exemplu, Ebay marea BRITANIE), url-ul de gazdă (de exemplu, www.ebay.co.uk), și o adresă url imagine. Eu hartă acest răspuns pe datele mele de clasa care arată în felul următor:
data class(
val name: String,
var url: String,
val icon: String,
var averagePing: Long = -1
)
url-ul este un var de proprietate ca înainte de a face apeluri pentru a obține valorile timpilor de latență, am nevoie pentru a adăuga https://, în scopul de a face cererea.
Fac toate acestea astfel:
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) }
}
}
}
Prima bucla pregătește datele mele. Linie după buclă transmite date la reciclare adaptor, în scopul de a arăta numele de gazdă, url-ul și pictograma imediat (asta toate lucrările de exemplu am un lucru de observator pentru LiveData), în timp ce eu sunt de așteptare pentru valorile timpilor de latență.
Cea de-a doua buclă pentru apeluri de funcție pentru a calcula valorile timpilor de latență pentru fiecare gazdă și updateHostList() funcția actualizează LiveData.
Acesta este modul în care funcțiile uite:
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
}
}
}
Toate acestea se întâmplă în viewModel. În prezent îmi actualizez lista de depunerea întreaga listă din nou, atunci când am schimba o proprietate a unui element de listă, care pare oribil pentru mine.
Intrebarea mea este: Cum pot actualiza doar o proprietate de gazdă și să-l reîmprospăta UI automat?
Multumesc anticipat
Edit: Mi observator arată astfel:
viewModel.hostListLiveData.observe(this, Observer { adapter.updateData(it) })
Și updateData() arată astfel:
fun updateData(freshHostList: List<Host>) {
hostList.clear()
hostList.addAll(freshHostList)
notifyDataSetChanged()
}
@ArpitShukla, nu sugerez că ar fi 2 funcțiile de actualizare? unul pentru a arăta lista inițială și alta să actualizare pe element din listă? Sau aș pune ambele notifyDataSetChanged() și notifyItemChanged() în updateData()?
Edit2: mi-a schimbat funcția de a face apel asincron.