कैसे बनाने के लिए LiveData<MutableList<T>> अद्यतन जब मैं एक संपत्ति को बदलने के लिए टी?

0

सवाल

मैं कर रहा हूँ एक app हो जाता है, जो (छद्म) विलंबता मूल्यों द्वारा एक अनुरोध बनाने के लिए कुछ यूआरएल और रिकॉर्डिंग कैसे लंबे समय है कि ले जाएगा.

सबसे पहले, मैं का उपयोग पुराना वापस पाने के लिए एक JSON प्रतिक्रिया से एक वेब सर्वर. इस प्रतिक्रिया में शामिल हैं: नाम के मेजबान (जैसे Ebay ब्रिटेन), यूआरएल के मेजबान (उदा. www.ebay.co.uk), और एक छवि का url. मैं नक्शा इस प्रतिक्रिया पर अपने डेटा वर्ग है जो निम्न के जैसा दिखता है:

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

यूआरएल की एक किस्म के रूप में संपत्ति बनाने से पहले कॉल प्राप्त करने के लिए विलंबता मूल्यों, मैं जोड़ने के लिए की जरूरत 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) }
        }
    }
}

पहली पाश के लिए तैयार हो जाओ! के बाद लाइन में पाश के लिए प्रस्तुत करने के लिए डेटा recycler एडाप्टर दिखाने के क्रम में, होस्ट नाम, यूआरएल और आइकन सीधे (यह सब काम करता है यानी मैं काम कर रहे एक पर्यवेक्षक के लिए LiveData), जबकि मैं इंतज़ार कर रहा हूँ के लिए विलंबता मूल्यों.

दूसरी पाश के लिए कॉल समारोह की गणना करने के लिए विलंबता मूल्यों के लिए प्रत्येक मेजबान और updateHostList() समारोह अद्यतन LiveData.

यह कैसे कार्य देखो:

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

इस सब के सब में होता है viewModel. वर्तमान में मैं अद्यतन हूँ मेरी सूची प्रस्तुत करने के द्वारा पूरी सूची फिर से, जब मैं बदलने के लिए एक संपत्ति के एक तत्व की सूची है, जो लगता है मेरे लिए भयानक.

मेरा सवाल है: मैं कैसे कर सकते हैं अद्यतन केवल एक ही संपत्ति के मेजबान है और यह ताज़ा यूआई स्वचालित रूप से?

धन्यवाद अग्रिम में

संपादित करें: अपने पर्यवेक्षक इस तरह दिखता है:

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: बदला मेरी समारोह कॉल करने के लिए बनाने के लिए यह async.

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

सबसे अच्छा जवाब

1

आप कर सकते हैं पर विचार करने के लिए अद्यतन आइटम से मनाया hostListLiveData का उपयोग कर notifyItemChanged(position) इसके बजाय notifyDataSetChanged() में अपने adapter.

notifyItemChanged(position) एक आइटम बदल घटना है, जो अद्यतन केवल सामग्री मद की.

संपादित करें:
आप उपयोग कर रहे हैं notifyDataSetChanged() पर सामग्री को अद्यतन डेटा के जो कारण करने के लिए relayout और rebind के 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

यह काम करता है, लेकिन मुझे नहीं लगता कि यह करने के लिए संबंधित है LiveData. मैंने बनाया है एक सरल recycler देखने से पता चलता है जो एक सूची का परीक्षण करने के लिए इस है, और मैं बस एडाप्टर कहा जाता है.notifyItemChanged(स्थिति). यह काम किया, लेकिन मैं देख नहीं कैसे यह करने के लिए संबंधित है LiveData. स्पष्ट कर सकता, कृपया? पुनश्च: मैं अद्यतन हूँ सवाल है दिखा कैसे अपने पर्यवेक्षक काम करता है, मुझे लगता है कि आप दे देंगे कुछ अधिक संदर्भ
SpawnTheTronix

हाँ, यह नहीं है के बारे में LiveData, यह कारण है करने के लिए जिस तरह से अद्यतन करने के RecyclerView. आप उपयोग कर रहे हैं notifyDataSetChanged() पर सामग्री को अद्यतन अपने डेटा (जैसे अद्यतन host और ping). के notifyDataSetChanged() पूरी तरह से rebind और relayout सभी दृश्य डेटा.
Putra Nugraha

मैं भी उपयोग करने की कोशिश की ListAdapter के बजाय RecyclerView.Adapter, यह हासिल की अपने वांछित कार्यक्षमता के रूप में अच्छी तरह से. क्या आपको पता है कि क्या बेहतर है, का उपयोग कर notifyDataSetChanged() या एक ListAdapter? के रूप में दूर के रूप में मैं समझता हूँ notifyDataSetChanged(), यह अद्यतन देखें (पंक्ति में RecyclerView) जो आपको यह बताने के लिए अद्यतन.ListAdapter चेक में मतभेद के लिए नई सूची और सूची, और उसके बाद अद्यतन को बदल क्षेत्र (यानी, एक TextView) के लिए नए मूल्य (हालांकि मुझे यकीन नहीं है अगर यह अद्यतन केवल TextView या पूरी पंक्ति, जो मामले में वहाँ होगा कोई फर्क पड़ता है?).
SpawnTheTronix

ListAdapter हुड के अंतर्गत का उपयोग कर रहा है AsyncListDiffer मदद करने के लिए की गणना के बीच मतभेद संग्रहीत डेटा और उपलब्ध कराए गए आंकड़ों, और कैसे यह डेटा की तुलना पर आधारित है परिभाषित हालत में DiffUtil.ItemCallback. AFAIK, ListAdapter नहीं होगा relayout अपने RecyclerViewहै , लेकिन केवल अद्यतन डेटा संशोधित. अच्छी तरह से, ListAdapter भी एक व्यवहार्य समाधान के लिए अपने मामले में वैसे भी
Putra Nugraha

अन्य भाषाओं में

यह पृष्ठ अन्य भाषाओं में है

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

इस श्रेणी में लोकप्रिय

लोकप्रिय सवाल इस श्रेणी में