วิธีที่จะทำให้ LiveData<MutableList<ที>>ปรับปรุงตอนที่ฉันเปลี่ยนเป็นทรัพย์สินของที?

0

คำถาม

ฉันกำลังทำโปรแกรที่ได้รับ(ชั่วโมง)latency ค่าโดยทำการร้องขอให้ไปบางที่อยู่ url และบันทึกเสียงนานแค่ไหนที่จะรับมัน

ก่อน,ฉันใช้ retrofit ได้ LANGUAGE การตอบสนออกจากเว็บเซิร์ฟเวอร์ นี้มีการตอบสนอ:ชื่อโฮสต์(e.g. อีเบย์งกฤษ)ผู้ที่อยู่ url ของโฮสต์(e.g. www.ebay.co.uk),และเป็นภาพที่อยู่ url ได้ ฉันแผนที่นี้การตอบรับข้อมูลชั้นเรียนซึ่งดูเหมือนว่าต่อไปนี้:

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

ที่อยู่ url เป็น variance ทรัพย์สินเป็นก่อนที่ทำประวัติการโทร.ไปที่ latency ค่าของฉันต้องการจะเพิ่มเติม http://เพื่อที่จะทำสิ่งที่ร้องขอมาต้องการ.

ฉันกำลังทำอะไรองทั้งหมดนี้เหมือนแล้ว:

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

คนแรกสำหรับเรื่องของฉันเอาเข็มทิศมา\เขาหมายถึงข้อมูลออกมา เส้นหลังสำหรับวง submits ข้อมูลที่ recycler อะแดปเตอร์เพื่อแสดงเครื่องชื่อที่อยู่ url และไอคอนตรงไป(ทั้งหมดนี่ทำงาน i.e. ฉันมีงานที่ต้องทำสังเกตการณ์ต้องสำหรับ LiveData)ขณะที่ฉันกำลังรอสำหรับ latency ค่า.

ที่สองสำหรับเรื่องเรียกฟังก์ชันที่จะคำนวณ latency อนค่าสำหรับกันและเครื่องและ 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. ตอนนี้ฉันกำลังปรับปรุงรายชื่อของฉันโดย submitting ทั้งหมดรายชื่ออีกครั้งตอนที่ฉันเปลี่ยนคนทรัพย์สินของธาตุหนึ่งของรายการซึ่งดูเหมือนน่ากลัวฉันนะ

คำถามคือ:ทำไมฉันปรับปรุงเดียวที่ทรัพย์สินของเครื่องและมีการเรียกปรับปรุงส่วนติดต่อผู้ใช้ให้อัตโนมัติ?

ขอบคุณล่วงหน้า

แก้ไขของผมผู้สังเกตการณ์ดูเหมือนนี้:

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 อยู่ในอะแดปเตอร์ e.g.

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() บกำลังปรับปรุงเนื้อหาของข้อมูลของคุณ(e.g. กำลังปรับปรุง host แล้ว ping). คน notifyDataSetChanged() จะเต็ม rebind และ relayout ที่เห็นทั้งหมดข้อมูล
Putra Nugraha

ฉันยังพยายามใช้ ListAdapter แทนที่จะเป็น RecyclerView.Adapterมันทำจะประสบผลสำเร็จของฉันที่ต้องการ functionality เช่นกัน คุณรู้ว่ามันคืออะไรดีกว่านี้โดยใช้ notifyDataSetChanged() หรือเป็น ListAdapter? เท่าที่ฉันเข้าใจ notifyDataSetChanged()มันปรับปรุงมุมมอง(แถวอยู่ RecyclerView)ซึ่งเธอบอกมันเพื่อปรับปรุงListAdapter เช็คสำหรับความแตกต่างในรายการใหม่และเก่าของรายการและจากนั้นก็ปรับปรุงที่เปลี่ยนสนาม(i.e. น 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ý
..................................................................................................................

ดังอยู่ในนี้หมวดหมู่

ดังคำถามอยู่ในนี้หมวดหมู่