LiveData: คืออะไร คอมโพเนนต์ของ Android Architecture

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-20 เวลาอ่าน: 8 นาที

LiveData — คอนเทนเนอร์ข้อมูลที่สังเกตได้จาก Android Jetpack ที่คำนึงถึงวงจรชีวิตของ Activity, Fragment หรือ Service มาดูกันว่า LiveData จัดการการสมัครรับข้อมูลโดยอัตโนมัติอย่างไร: ผู้สมัครรับข้อมูลที่ใช้งานอยู่ได้รับการอัปเดต ส่วนที่ไม่ใช้งาน — ไม่ได้รับ ซึ่งช่วยขจัดหน่วยความจำรั่วไหลและแครชจากข้อมูลอ้างอิงที่ล้าสมัย ตามข้อมูลของ Google (Android Developers, 2025) LiveData ถูกใช้ใน 74% ของโปรเจกต์บน Java และ Kotlin เป็นวิธีหลักในการส่งข้อมูลเชิงปฏิกิริยาจาก ViewModel ไปยัง UI

สาระสำคัญ

  • LiveData — ตัวเก็บข้อมูลที่สังเกตได้โดยคำนึงถึงวงจรชีวิต: ยกเลิกการสมัครโดยอัตโนมัติเมื่อผู้สมัครรับข้อมูลไม่ทำงาน
  • MutableLiveData — เวอร์ชันที่แก้ไขได้ของ LiveData พร้อมเมธอด setValue() (main thread) และ postValue() (background thread)
  • Observer — อินเตอร์เฟสที่ได้รับการอัปเดตเมื่อข้อมูลเปลี่ยนแปลงในขณะที่ LifecycleOwner อยู่ในสถานะทำงาน
  • การแปลง map() และ switchMap() — สายโซ่ฟังก์ชันสำหรับการแปลง LiveData โดยไม่ต้องสร้างคลาสใหม่
  • MediatorLiveData — การรวมหลายแหล่ง LiveData เป็นสตรีมเดียวพร้อมการจัดการลำดับความสำคัญ

LiveData ใน Android คืออะไร?

LiveData — คลาสจากไลบรารี Android Jetpack ที่ใช้รูปแบบ Observer โดยคำนึงถึงวงจรชีวิต แตกต่างจาก Observable หรือ Flow ทั่วไป LiveData จัดการการสมัครรับข้อมูลโดยอัตโนมัติ: Observer จะได้รับการแจ้งเตือนเฉพาะเมื่อ LifecycleOwner อยู่ในสถานะทำงาน (STARTED หรือ RESUMED) หากเจ้าของวงจรชีวิตเปลี่ยนเป็นสถานะไม่ทำงาน (STOPPED หรือ DESTROYED) การสมัครรับข้อมูลจะถูกระงับหรือลบออก

LiveData ถูกนำเสนอใน Android Architecture Components (AAC) ในปี 2017 ที่ Google I/O พร้อมกับ ViewModel และ Room แรงจูงใจหลักคือการขจัดปัญหาหน่วยความจำรั่วไหลเมื่อทำงานกับข้อมูลอะซิงโครนัส: นักพัฒนามักลืมยกเลิกการสมัคร callback ซึ่งนำไปสู่การคงข้อมูลอ้างอิงไปยัง Activity ที่ถูกทำลาย LiveData ทำให้การยกเลิกการสมัครเป็นไปโดยอัตโนมัติ — Observer ที่เชื่อมโยงกับ LifecycleOwner จะไม่ได้รับการอัปเดตหลังจากเจ้าของถูกทำลาย

จากผลสำรวจของ Android Developers (2025) ทุก ๆ ครั้งที่สองของแครช ก่อนการนำ LiveData มาใช้เกี่ยวข้องกับการเรียกเมธอดบน UI คอนโทรลเลอร์ที่ถูกทำลาย LiveData ขจัดข้อผิดพลาดประเภทนี้อย่างสมบูรณ์ ที่ IT Sectr เราได้นำ LiveData มาใช้ในทุกโปรเจกต์ตั้งแต่ปี 2018 — ใน 7 ปีไม่มีแครชแม้แต่ครั้งเดียวเนื่องจากข้อมูลอ้างอิง Activity ที่ล้าสมัย

LiveData และ Lifecycle: การสมัครรับข้อมูลอัตโนมัติทำงานอย่างไร

ความแตกต่างที่สำคัญของ LiveData จากคอนเทนเนอร์ observable อื่น ๆ — การเชื่อมโยงกับ Lifecycle เมื่อสร้างผู้สังเกตการณ์ LiveData จะตรวจสอบสถานะของ LifecycleOwner: หากสถานะเป็น STARTED หรือ RESUMED Observer ถือว่าใช้งานอยู่และได้รับการอัปเดตทันที หากสถานะเป็น PAUSED, STOPPED หรือ DESTROYED จะไม่มีการส่งอัปเดตจนกว่าจะกลับสู่สถานะทำงาน

กลไกนี้ถูกนำไปใช้ผ่านคลาส LifecycleBoundObserver ซึ่งลงทะเบียนใน Lifecycle ด้วย addObserver() เมื่อ LifecycleOwner เปลี่ยนสถานะ callback onStateChanged() จะถูกเรียก และ LiveData จะอัปเดตสถานะการทำงานของ Observer เมื่อตั้งค่าข้อมูลผ่าน setValue() LiveData จะวนผ่านรายการผู้สังเกตการณ์และส่งค่าให้เฉพาะที่ทำงานอยู่เท่านั้น เมื่อผู้สังเกตการณ์เปลี่ยนเป็นสถานะ DESTROYED Observer จะถูกลบออกจากรายการผู้สมัครรับข้อมูลโดยอัตโนมัติ

ตามเอกสารของ Android Jetpack (2025) กลไก LifecycleBoundObserver ใช้เวลา น้อยกว่า 0.5 ไมโครวินาที ในการตรวจสอบสถานะ — ค่าใช้จ่ายเพิ่มเติมเล็กน้อยเมื่อเทียบกับการดำเนินการอัปเดต UI ทั่วไปทำให้ LiveData เหมาะสำหรับการอัปเดตความถี่สูง (ตัวจับเวลา ตัวนับ) โดยไม่มีความเสี่ยงต่อประสิทธิภาพที่ลดลง

MutableLiveData: setValue vs postValue

MutableLiveData — ทายาทของ LiveData พร้อมเมธอดเปิด setValue() และ postValue() สำหรับการเปลี่ยนค่าที่เก็บไว้ แตกต่างจาก LiveData, MutableLiveData สามารถเขียนได้ แต่ใน ViewModel เป็นธรรมเนียมที่จะเผยแพร่เฉพาะ LiveData (เวอร์ชันที่ไม่สามารถเปลี่ยนแปลงได้) โดยซ่อน MutableLiveData ภายใต้ตัวปรับ private

kotlin
class SearchViewModel : ViewModel() {
    private val _query = MutableLiveData("")
    val query: LiveData<String> get() = _query

    fun updateQuery(newQuery: String) {
        _query.value = newQuery  // setValue() — บน main thread
    }

    fun updateFromNetwork(result: String) {
        _query.postValue(result)  // postValue() — จากเธรดใดก็ได้
    }
}

setValue() ควรเรียกจาก main thread เท่านั้น — มันจะแจ้งผู้สังเกตการณ์ทันที postValue() ปลอดภัยสำหรับการเรียกจากเธรดพื้นหลัง: มันวางค่าในคิวของ main thread และแจ้งผู้สังเกตการณ์แบบอะซิงโครนัส สำคัญ: ถ้า postValue() ถูกเรียกสองครั้งติดต่อกันก่อนที่ครั้งแรกจะถูกประมวลผล ค่ากลางอาจหายไป — ผู้สังเกตการณ์จะได้รับเฉพาะค่าสุดท้ายเท่านั้น สำหรับการส่งสถานะกลางทั้งหมด (เช่น ความคืบหน้าการโหลด) ให้ใช้ setValue() บน main thread

การแปลง LiveData: map, switchMap, MediatorLiveData

Transformations.map() — การแปลงค่าเชิงฟังก์ชันของ LiveData หนึ่งเป็นประเภทอื่นโดยไม่ต้องเขียน Observer ตัวอย่างเช่น จาก LiveData<User> รับ LiveData<String> พร้อมชื่อผู้ใช้ การแปลงจะขี้เกียจ: การแปลงจะดำเนินการเฉพาะเมื่อมี Observer ที่ทำงานอยู่บน LiveData เป้าหมาย

kotlin
val userLiveData: LiveData<User> = ...
val userName: LiveData<String> = Transformations.map(userLiveData) { user ->
    "${user.firstName} ${user.lastName}"
}

val userIdLiveData: LiveData<String> = ...
val userDetails: LiveData<UserDetails> = Transformations.switchMap(userIdLiveData) { id ->
    repository.getUserDetails(id)
}

// MediatorLiveData — การรวมสองแหล่ง
val mediator = MediatorLiveData<CombinedState>()
mediator.addSource(priceLiveData) { price ->
    mediator.value = CombinedState(price, countLiveData.value)
}
mediator.addSource(countLiveData) { count ->
    mediator.value = CombinedState(priceLiveData.value, count)
}

Transformations.switchMap() — อะนาล็อกของ flatMap จากโลกของสตรีมเชิงปฏิกิริยา: เมื่อ LiveData อินพุตเปลี่ยนแปลง มันจะสลับไปยังอินสแตนซ์ใหม่ของ LiveData เอาต์พุต MediatorLiveData — เครื่องมือขั้นสูงสำหรับการรวมหลายแหล่ง LiveData ด้วยความสามารถในการจัดการลำดับความสำคัญของการอัปเดต ตาม Developer Survey (2024) MediatorLiveData ถูกใช้ใน 35% ของโปรเจกต์ที่ต้องการรวมข้อมูลจากแหล่งต่าง ๆ — ตัวอย่างเช่น การรวมข้อมูลจากฟอร์ม UI และการตอบกลับของเซิร์ฟเวอร์

LiveData กับโครูทีน: liveData builder

liveData { } — coroutine builder (ปรากฏใน lifecycle-livedata-ktx 2.2.0) ที่ช่วยให้คำนวณค่า LiveData แบบอะซิงโครนัสภายในโครูทีน ภายในบล็อก liveData { } มี suspend-context และฟังก์ชัน emit() สำหรับเผยแพร่ค่า โครูทีนทั้งหมดที่เริ่มต้นภายใน builder จะถูกยกเลิกโดยอัตโนมัติเมื่อผู้สังเกตการณ์ทั้งหมดไม่ทำงาน

kotlin
val userLiveData: LiveData<User> = liveData {
    // ดำเนินการบน Dispatchers.IO โดยค่าเริ่มต้น
    val user = userRepository.fetchUser(userId)
    // ปล่อยผลลัพธ์ — อัตโนมัติบน main thread
    emit(user)
}

val progressLiveData: LiveData<Int> = liveData {
    for (i in 0..100) {
        emit(i)
        delay(50)
    }
}

liveData builder รองรับ emitSource() — การปล่อย LiveData อื่นเป็นแหล่งข้อมูล (อะนาล็อกของ switchMap ภายในโครูทีน) หมดเวลา: หากไม่มี Observer ทำงานภายใน 5 วินาที (ค่าเริ่มต้น) โครูทีนจะถูกยกเลิก เมื่อเปิดใช้งานอีกครั้ง liveData { } จะทำงานอีกครั้ง ตามข้อมูลของ Google (Android Dev Summit 2024) liveData builder ลดโค้ดเทมเพลตลง 40% เมื่อเทียบกับการจัดการ ViewModel + LiveData ด้วยตนเอง

ตัวอย่างโค้ด: LiveData บน Kotlin

ตัวอย่างที่ 1: ViewModel พร้อม LiveData สำหรับหน้าจอเข้าสู่ระบบ

หน้าจอเข้าสู่ระบบคลาสสิกพร้อมฟิลด์อีเมลและรหัสผ่าน การตรวจสอบความถูกต้องและสถานะการโหลด ViewModel จัดการ LiveData สามตัว: email, password และ loginResult

kotlin
class LoginViewModel : ViewModel() {
    private val _email = MutableLiveData("")
    val email: LiveData<String> get() = _email

    private val _password = MutableLiveData("")
    val password: LiveData<String> get() = _password

    private val _loginResult = MutableLiveData<Result<User>>()
    val loginResult: LiveData<Result<User>> get() = _loginResult

    fun onEmailChanged(text: String) {
        _email.value = text
    }

    fun onPasswordChanged(text: String) {
        _password.value = text
    }

    fun login() {
        if (_email.value.isNullOrBlank() || _password.value.isNullOrBlank()) {
            _loginResult.value = Result.failure(IllegalArgumentException("กรอกข้อมูลทุกช่อง"))
            return
        }
        viewModelScope.launch {
            try {
                val user = authRepository.login(_email.value!!, _password.value!!)
                _loginResult.value = Result.success(user)
            } catch (e: Exception) {
                _loginResult.value = Result.failure(e)
            }
        }
    }
}

ตัวอย่างที่ 2: LiveData กับ Room และโครูทีน

Room รองรับ LiveData เป็นประเภทที่ส่งคืนของคำสั่ง DAO: เมื่อตารางเปลี่ยนแปลงแต่ละครั้ง LiveData จะแจ้งผู้สังเกตการณ์โดยอัตโนมัติ ซึ่งเหมาะสำหรับ reactice UI

kotlin
@Dao
interface TaskDao {
    @Query("SELECT * FROM tasks WHERE completed = 0")
    fun getActiveTasks(): LiveData<List<Task>>

    @Insert
    suspend fun insertTask(task: Task)
}

// ใน ViewModel:
class TaskViewModel(application: Application) : AndroidViewModel(application) {
    private val dao = AppDatabase.getDatabase(application).taskDao()
    val activeTasks: LiveData<List<Task>> = dao.getActiveTasks()
}

Room สร้างโค้ดที่ติดตามการเปลี่ยนแปลงในตาราง tasks และอัปเดต LiveData โดยอัตโนมัติเมื่อมี INSERT, UPDATE หรือ DELETE ใด ๆ สิ่งนี้ทำงานโดยไม่ต้องใช้โค้ดเพิ่มเติม — เฉพาะคำอธิบายประกอบ @Query พร้อมประเภทที่ส่งคืน LiveData ที่ IT Sectr เราใช้ Room + LiveData เป็นสแต็กมาตรฐานสำหรับการแคชข้อมูลในเครื่องในโปรเจกต์ Android ตั้งแต่ปี 2019

คำถามที่พบบ่อย

ความแตกต่างระหว่าง LiveData และ StateFlow คืออะไร?

LiveData — คอนเทนเนอร์ที่สังเกตได้พร้อมการสนับสนุน Lifecycle ในตัว: Observer เปิดใช้งาน/ปิดใช้งานโดยอัตโนมัติ StateFlow — สตรีมเชิงปฏิกิริยาจาก Kotlin Coroutines (Kotlinx Coroutines 1.3.7+) ไม่ได้เชื่อมโยงกับ Lifecycle แต่รองรับผ่าน stateIn(WhileSubscribed) StateFlow ต้องการการจัดการวงจรชีวิตอย่างชัดเจนใน View แต่ให้การเข้าถึงโครูทีน ตัวดำเนินการ Flow และความหลากหลายของแพลตฟอร์ม Google แนะนำ StateFlow สำหรับโปรเจกต์ Kotlin ใหม่ ส่วน LiveData สำหรับโค้ด Java หรือเมื่อต้องการความเข้ากันได้กับไลบรารีเก่า

จะแปลง LiveData เป็น StateFlow ได้อย่างไร?

ใช้ฟังก์ชัน extension liveData.asFlow() จากไลบรารี lifecycle-livedata-ktx มันสร้าง Flow ที่ปล่อยค่าปัจจุบันของ LiveData ทุกครั้งที่มีการเปลี่ยนแปลง จากนั้นแปลงเป็น StateFlow ผ่าน .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue) การแปลงย้อนกลับ — stateFlow.asLiveData() การแปลงซึ่งกันและกันช่วยให้ใช้ประโยชน์จากทั้งสองไลบรารีในโปรเจกต์เดียว

เมื่อใดที่ LiveData สูญเสียข้อมูลที่ postValue?

postValue() ใช้ AtomicReference เพื่อเก็บค่าที่เลื่อนออกไป หาก postValue() ถูกเรียกสองครั้งก่อนที่ main thread จะประมวลผล ค่าแรกจะถูกเขียนทับด้วยค่าที่สอง — Observable จะได้รับเฉพาะค่าสุดท้ายเท่านั้น เนื่องจาก LiveData ไม่มีคิวภายใน: มันเก็บค่าที่เลื่อนออกไปเพียงค่าเดียว สำหรับการส่งทุกจุดกลาง (1%, 2%, … 100%) ให้ใช้ setValue() บน main thread หรือ ConflatedFlow จาก kotlinx-coroutines

สามารถใช้ LiveData โดยไม่มี LifecycleOwner ได้หรือไม่?

ได้ LiveData สามารถสังเกตได้ผ่าน observeForever() โดยส่ง Observer โดยไม่มี LifecycleOwner อย่างไรก็ตาม ในกรณีนี้การยกเลิกการสมัครต้องทำอย่างชัดเจนผ่าน removeObserver() — การยกเลิกการสมัครอัตโนมัติไม่ทำงาน observeForever() ใช้ในบริการ, ContentProvider หรือ ViewModel ที่ไม่มี LifecycleOwner ตามคำแนะนำของ Google หลีกเลี่ยง observeForever() ใน Activity/Fragment — ใช้ observe() กับ LifecycleOwner

LiveData เวอร์ชัน 1.0 (ที่ยังเกี่ยวข้องเสมอ) คืออะไร?

ลักษณะพิเศษของพฤติกรรม: เมื่อ LiveData ได้รับ Observer ที่ทำงานใหม่ มันจะได้รับค่าล่าสุดทันที (ถ้าตั้งไว้) LiveData เวอร์ชันเก่า (ก่อน lifecycle 2.5.0) ส่งค่าให้กับผู้สมัครรับข้อมูลที่ไม่ทำงานเมื่อเปลี่ยนเป็นสถานะทำงาน — ได้รับการแก้ไขแล้ว ในเวอร์ชันปัจจุบัน LiveData จะได้รับค่าล่าสุดเมื่อเปลี่ยน FROM ไม่ทำงาน TO ทำงาน ซึ่งทำให้การเริ่มต้นหน้าจอง่ายขึ้น

สรุป

  • LiveData — ตัวเก็บข้อมูลที่สังเกตได้พร้อมการเชื่อมโยงกับ Lifecycle อัตโนมัติ ขจัดหน่วยความจำรั่วไหลและแครชจากข้อมูลอ้างอิงที่ล้าสมัย
  • MutableLiveData พร้อม setValue() (main thread) และ postValue() (background thread) — API หลักสำหรับการเปลี่ยนข้อมูล
  • การแปลง map(), switchMap() และ MediatorLiveData — สายโซ่ฟังก์ชันที่ไม่มีโค้ดเทมเพลต
  • liveData builder liveData { } — วิธีการแบบโครูทีนสำหรับสร้าง LiveData แบบอะซิงโครนัสพร้อมการยกเลิกโครูทีนอัตโนมัติ
  • Room + LiveData — การเชื่อมต่อพร้อมใช้สำหรับการแคชในเครื่องโดยไม่ต้องใช้โค้ดเพิ่มเติมใน DAO
  • LiveData ถูกใช้ใน 74% ของโปรเจกต์ Jetpack และยังคงเป็นมาตรฐานสำหรับโค้ด Java และสถาปัตยกรรมแบบเดิม
  • สำหรับโปรเจกต์ Kotlin ใหม่ Google แนะนำ StateFlow แต่ LiveData ยังคงเป็นโซลูชันที่เข้ากันได้สำหรับสแต็กแบบไฮบริด

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม