Robím aplikáciu, ktorá dostane (pseudo) latencie hodnoty tým, že požiadavku na niektoré adresy url a nahrávanie ako dlho to bude trvať.
Najprv som použiť retrofit dostať odpoveď JSON z webového servera. Táto odpoveď obsahuje: názov hostiteľa (napr. Ebay UK), url hostiteľa (napr. www.ebay.co.uk) a adresu url obrázku. Som mapu túto odpoveď na môj údaje trieda, ktorá vyzerá takto:
data class(
val name: String,
var url: String,
val icon: String,
var averagePing: Long = -1
)
url je var majetku ako pred vykonaním hovory sa dostať latencia hodnoty, musím pridať https://, aby žiadosť.
Robím to všetko ako tak:
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) }
}
}
}
Prvý pre slučky pripravuje dáta. Riadok po pre slučky predloží údaje recyklátor adaptér, aby sa zobrazil názov hostiteľa, adresu url a ikonu rovno (to všetko pracuje, t. j. mám pracovných pozorovateľa pre LiveData), zatiaľ čo ja čakám na latenciu hodnoty.
Druhý pre slučky hovorov funkcia na výpočet latencie hodnoty pre každý hosť a updateHostList() funkcia aktualizuje LiveData.
To je, ako funkcie vzhľad:
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
}
}
}
To všetko sa deje v viewModel. V súčasnej dobe som sa aktualizuje môj zoznam odoslaním celý zoznam znovu, keď som sa zmeniť jednu vlastnosť jeden prvok zoznamu, ktorý sa zdá hrozné pre mňa.
Moja otázka je: Ako som sa aktualizovať len jednu vlastnosť hosť a majú ho obnoviť UI automaticky?
Vďaka vopred
Edit: Môj pozorovateľ vyzerá takto:
viewModel.hostListLiveData.observe(this, Observer { adapter.updateData(it) })
A updateData() vyzerá takto:
fun updateData(freshHostList: List<Host>) {
hostList.clear()
hostList.addAll(freshHostList)
notifyDataSetChanged()
}
@ArpitShukla, navrhujete by som 2 update funguje? jeden zobrazuje počiatočné zoznam a ďalšie aktualizovať na položku zoznamu? Alebo by som len dal obe notifyDataSetChanged() a notifyItemChanged() v updateData()?
Edit2: zmenil moje volanie funkcie, aby to async.