Dělám aplikaci, která dostane (pseudo) hodnoty latence tím, že žádost, aby některé adresy url a nahrávání, jak dlouho to bude trvat.
Za prvé, jsem se použít dodatečná získat JSON odpověď z webového serveru. Tato reakce obsahuje: název hostitele (např. Ebay UK), url hostitele (např. www.ebay.co.uk), a adresu url obrázku. Já mapě to reakce na moje data třídy, které vypadá jako následující:
data class(
val name: String,
var url: String,
val icon: String,
var averagePing: Long = -1
)
url je var ubytování jako před provedením volání získat latence hodnoty, musím přidat https:// tak, aby žádost.
Dělám vše tak jako:
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) }
}
}
}
První smyčka se připravuje mé údaje. Řádku po pro smyčce odešle data k recyklaci adaptér, aby bylo možné zobrazit název hostitele, adresa url a ikona rovnou (to všechno funguje, tj. mám pracovní pozorovatele pro LiveData), zatímco čekám na latence hodnoty.
Druhý cyklus for volá funkci pro výpočet hodnoty latence pro každého hostitele a updateHostList() funkce aktualizace LiveData.
To je, jak funguje vypadat:
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še se děje v viewModel. V současné době jsem aktualizovat můj seznam předložením celý seznam znovu, když jsem se změnit jednu vlastnost jeden prvek seznamu, který se zdá být hrozné pro mě.
Moje otázka je: Jak mohu aktualizovat pouze jednu vlastnost z hostitele a mít ji aktualizovat UI automaticky?
Díky předem
Edit: Můj pozorovatele vypadá takto:
viewModel.hostListLiveData.observe(this, Observer { adapter.updateData(it) })
A updateData() vypadá takto:
fun updateData(freshHostList: List<Host>) {
hostList.clear()
hostList.addAll(freshHostList)
notifyDataSetChanged()
}
@ArpitShukla, navrhuješ bych 2 aktualizace funkce? jeden pro zobrazení původního seznamu a další aktualizace na položku v seznamu? Nebo bych prostě dal obě notifyDataSetChanged() a notifyItemChanged() v updateData()?
Edit2: změnil volání funkce, aby se to asynchronní.