วิธีการสื่อสารระหว่างแฟรกเมนต์และกิจกรรมโดยใช้ ViewModel

การสื่อสารเป็นหนึ่งในหัวข้อที่สำคัญที่สุดสำหรับนักพัฒนาและสามารถทำได้หลายวิธี แต่ความท้าทายคือการทำในวิธีที่ง่ายที่สุดและเพิ่มประสิทธิภาพ เราสามารถทำได้โดยใช้การยื่นแบบคงที่ แต่มันจะเกิดปัญหาหน่วยความจำ เพื่อหลีกเลี่ยงปัญหาหน่วยความจำนักพัฒนาหลายคนทำอะไรเช่น

(กิจกรรมเป็น MainActivity) .passDataToAnotherFragment ()

มีปัญหากับวิธีนี้คืออะไร? มันผูกชิ้นส่วนกับกิจกรรมที่เฉพาะเจาะจงลดการใช้งานอีกครั้ง แล้ววิธีที่แนะนำคืออะไร?

Google แนะนำให้ใช้อินเทอร์เฟซ (ก่อน ViewModel) doc สำหรับสิ่งนี้เราต้องใช้ส่วนต่อประสานในคลาสกิจกรรม แฟรกเมนต์ย่อยจะเก็บการอ้างอิงของอินเตอร์เฟสที่ใช้โดยกิจกรรม ข้อมูลจะถูกส่งผ่านวิธีการเชื่อมต่อ

ลำดับงานของการสื่อสารโดยใช้อินเตอร์เฟส

สมมติว่าสถานการณ์ง่าย ๆ ที่เรามีสองส่วนภายใต้กิจกรรมเดียวกันอันที่หนึ่งเพื่อใส่ตัวเลขและอีกอันหนึ่งคือการแสดงคู่ (อินพุต x 2) กิจกรรมจะแสดงข้อความอินพุตของคุณ 123 เช่นนี้

คุณลองจินตนาการดูว่าเราต้องเขียนโค้ดจำนวนเท่าใดและต้องรับมือกับสถานการณ์จำนวนเท่าใด ฉันไม่ได้ลงรายละเอียดเลยเนื่องจากบทความนี้เป็นเรื่องเกี่ยวกับวิธีแก้ปัญหาที่ง่ายที่สุดแทนที่จะแสดงให้เห็นถึงการใช้อินเทอร์เฟซ คุณสามารถค้นหาการใช้งานได้ที่นี่

ทางที่ง่าย

ที่นี่ ViewModel มาช่วยเราจากการจัดการสถานการณ์จำนวนมากและการใช้อินเทอร์เฟซ เราจำเป็นต้องสร้างคลาส ViewModel และสร้างอินสแตนซ์เป็นส่วน ๆ แต่ใช้ขอบเขตกิจกรรมเพื่อให้สามารถใช้งานได้สำหรับทุกส่วนของกิจกรรมรวมถึงตัวกิจกรรมเอง

ลำดับงานการสื่อสารโดยใช้ ViewModel

สร้างคลาส ViewModel

คลาส SharedViewModel: ViewModel () {
    val inputNumber = MutableLiveData  ()
}

ในการเปล่งหรือส่งผ่านข้อมูลจากแฟรกเมนต์อินพุตของเราให้สร้าง ViewModel ในขอบเขตกิจกรรม ในการทำเช่นนี้เราจะต้องผ่านการอ้างอิงกิจกรรมเป็นอาร์กิวเมนต์ของวิธีการ ViewModelProvides.of () ไม่เพียงแค่ส่งข้อมูลไปยังวัตถุ ViewModel เช่นนี้

กิจกรรม? .let {
    sharedViewModel = ViewModelProviders.of (it) .get (SharedViewModel :: class.java)
}

et_input.addTextChangedListener (วัตถุ: TextWatcher {
    แทนที่ความสนุก afterTextChanged (p0: แก้ไขได้) {}

    แทนที่ความสนุก beforeTextChanged (p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}

    ลบล้างความสนุกสนาน onTextChanged (txt: CharSequence?, p1: Int, p2: Int, p3: Int) {
        txt? .let {
            var input = 0
            if (txt.toString (). isNotEmpty ()) {
                input = txt.toString (). toInt ()
            }

            sharedViewModel? .inputNumber? .postValue (input)
        }
    }

ในกิจกรรมที่เราต้องสร้างตัวอย่างของ ViewModel ของเราและสังเกตข้อมูลที่ต้องการเช่นนี้

val sharedViewModel = ViewModelProviders.of (นี่) .get (SharedViewModel :: class.java)

sharedViewModel.inputNumber.observe (สิ่งนี้ผู้สังเกตการณ์ {
    มัน? .let {
        // ทำบางสิ่งกับตัวเลข
    }
})

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

สำหรับแฟรกเมนต์เอาต์พุตให้ทำเช่นนี้

กิจกรรม? .let {
    val sharedViewModel = ViewModelProviders.of (it) .get (SharedViewModel :: class.java)

    sharedViewModel.inputNumber.observe (สิ่งนี้ผู้สังเกตการณ์ {
    มัน? .let {
            // ทำบางสิ่งกับตัวเลข
        }
    })
}

แค่นั้นแหละ. รหัสที่มาสามารถพบได้ที่นี่

การอภิปราย StackOverflow

การเข้ารหัสที่มีความสุข