如何使其中<MutableList<T>>更新,当时我改变了财产的T?

0

的问题

我在做一个应用程序,它得到的(伪)延迟时间值是通过出请求的一些网址和录像多长时间,将采取。

第一,我使用的改型,会返回一个响应从一个网络服务器。 这种反应包括:主机名(例如Ebay联合王国),该网址的主机(例如 www.ebay.co.uk),和一个镜像网址。 我地图的这种反应到我的数据类如下:

data class(
    val name: String,
    var url: String,
    val icon: String,
    var averagePing: Long = -1
)

网址是一个var财产之前作出的呼吁得到延迟时间值,我需要增加https://为了使该请求。

我做的这一切就像这样:

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) }
        }
    }
}

第一次循环的准备我的数据。 线后对环数据提交给回收器,以显示主机名称,网址和标直接(这一切工作,即我们工作的观察员对其中),而我在等待等待时间值。

第二循环的呼吁函数计算的延迟时间值为每个主和updateHostList()功能就更新其中.

这是如何的功能看:

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
        }
    }
}

所有这一切都发生在模型. 目前我要更新我的名单提交整个列表再次当我改变的一个酒店中的一个元素的清单,这似乎太可怕了我。

我的问题是:如何更新,只有一个酒店的东道并刷新UI自动?

在此先感谢

编辑:我的观察者看起来像这样:

viewModel.hostListLiveData.observe(this, Observer { adapter.updateData(it) })

和updateData()看起来是这样的:

fun updateData(freshHostList: List<Host>) {
    hostList.clear()
    hostList.addAll(freshHostList)
    notifyDataSetChanged()
}

@ArpitShukla,你建议我有2个更新的功能吗? 一个表示的初步清单和另一个更新项目的清单? 或者我只是把这两个notifyDataSetChanged()和notifyItemChanged()在updateData()?

Edit2:改变我的功能的电话,使它异步.

android-livedata kotlin
2021-11-23 22:53:04
1

最好的答案

1

你可以考虑的更新项目,观察到从 hostListLiveData 使用 notifyItemChanged(position) 而不是 notifyDataSetChanged() 在你 adapter.

notifyItemChanged(position) 是的一个项目改变事件,这仅更新内容的项目。

编辑:
你使用 notifyDataSetChanged() 在更新内容的数据,这造成要重新布局和重新绑定的 RecyclerView 你没想到。 因此你应该更新内容的数据的使用 notifyItemChanged(position).

我认为您可以创建一个新的功能,用于更新你的 RecyclerView 在适配器例如

fun updateHostAndPing(updatedHost: Host, position: Int) {
    hostList[position].apply {
        url = updatedHost.url
        averagePing = updatedHost.averagePing
    }
    notifyItemChanged(position)
}

和你的观察员,可能需要检查它是否是新鲜的清单或更新名单

viewModel.hostListLiveData.observe(this, Observer { 
    if (adapter.itemCount == ZERO) {
        adapter.updateData(it) 
    } else {
        it.forEachIndexed { index, host ->
            adapter.updateHostAndPing(host, index) 
        }
    }
})
2021-11-24 23:12:08

这一工作,但我不认为这是关系到其中. 我做了一个简单的回收站查看,它显示了一系列的测试这个,我只是所谓的适配器。notifyItemChanged(位置)。 这个没有工作但我不看看它是如何与其中. 你能不能澄清一下,好吗? P.S.:我将更新该问题展示如何我观察员的工作,我认为会给你一些更多的情况下
SpawnTheTronix

是的,它不是关于其中,是由于更新 RecyclerView. 你使用 notifyDataSetChanged() 在更新内容的数据(例如更新 hostping). 的 notifyDataSetChanged() 将完全重新绑定和重新布局的所有可见的数据。
Putra Nugraha

我们还试图使用 ListAdapter 而不是的 RecyclerView.Adapter实现我所需的功能。 你知道什么是更好的使用 notifyDataSetChanged()ListAdapter? 据我了解 notifyDataSetChanged()它更新视图(列在 RecyclerView),你告诉它的更新。ListAdapter 检查差异的新的清单和旧名单,然后更新改变的领域(即一个 TextView)的新的价值(虽然我不确定如果它更新唯一的 TextView 或整个排,在这种情况下,就不会有差别吗?).
SpawnTheTronix

ListAdapter 引擎盖下的使用 AsyncListDiffer 要帮助的计算之间差异的存储数据和提供的数据,以及它如何进行比较的数据是基于定义的条件 DiffUtil.ItemCallback. 据我所知, ListAdapter 将不重新布局你 RecyclerView但只有更新修改的数据。 好了, ListAdapter 也是一个可行的解决方案对于你的情况呢
Putra Nugraha

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................