Sam Story

라이브 데이터 (LiveData) 본문

Android

라이브 데이터 (LiveData)

Sam H 2024. 4. 13. 13:33

1. 라이브 데이터 (LiveData) 란?

LiveData 는 Observable data holder class다.

 

쉽게 말하면 들고 있는 데이터에 대해 관찰을 하는 클래스라고 보면 된다.

 

LiveData는 액티비티, 프래그먼트, 서비스 등 안드로이드 컴포넌트의 Lifecycle에 영향을 받는다.

 

한마디로 LiveData는 컴포넌트들의 생명주기 상태가 활성화 되어있을 때만 data에 대한 update를 제공한다

 

LiveData 객체는 Observer 객체와 함께 사용된다.

 

LiveData가 들고 있는 데이터에 변화가 일어날 경우, LiveData는 등록된 Observer 객체에 변화를 알려주고

 

Observer의 onChanged() 메소드가 실행되게 된다.

 

자세한 내용은 아래의 예제를 보며 알아보겠다.

 

 

2.  예제

오늘 예제에서는 간다한 뷰모델 클래스를 만들어서 진행을 해보도록 하겠다.

 

MainViewModel class

package com.example.livedata_aac

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlin.random.Random

class MainViewModel : ViewModel() {
    
    // _name 변수를 MutableLiveData로 선언 및 초기화
    var _name: MutableLiveData<String> = MutableLiveData<String>()
    
    // setName() 메서드를 통해서 "sam" , "31" , "독서" 세가지 값중 하나를 랜덤으로 할당해줌
    fun setName() {

        val i: Int = Random.nextInt(3);
        var nameValue: String = ""

        when(i) {

            0 -> nameValue = "Sam"
            1 -> nameValue = "31"
            2 -> nameValue = "독서"

        }

        // _name.value에 세가지 값중 하나를 할당해줌
        Log.d("뷰모델", "setName: $nameValue")
        _name.value = nameValue

    }

}

 

 

 

메인 액티비티

package com.example.livedata_aac

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.lifecycle.Observer

class MainActivity : AppCompatActivity() {

    private lateinit var mainViewModel: MainViewModel

    lateinit var textView: TextView
    lateinit var button: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 메인 뷰모델 초기화
        mainViewModel = MainViewModel()

        textView = findViewById(R.id.textView)
        button = findViewById(R.id.button)

        // 옵저버 객체를 만들어준다.
        val nameObserver = Observer<String> {

            name-> textView.text = name

        }

        // LifecycleOwner가 들어갈 인수에 this(Activity)를 넣었다.
        // Observer패턴을 따르기 때문에 한번 observe를 해놓으면 별도로 값을 계속 초기화 해주지 않아도 된다.
        mainViewModel._name.observe(this,nameObserver)
       
        // 버튼 누를때마다 메인뷰모델의 setName() 메서드를 호출
        button.setOnClickListener {
        
            mainViewModel.setName()

        }

    }

}

 

 

 

메인 액티비티 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Fragment.Fragment_flower">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/flower_search"
            android:textColor="@color/black"
            android:layout_margin="20dp"
            android:textSize="23sp"
            android:textStyle="bold"/>

    </LinearLayout>


    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2">

        <TextView
            android:layout_margin="20dp"
            android:text="꽃 검색 결과"
            android:textSize="18sp"
            android:textColor="@color/black"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <ImageView
            android:id="@+id/iv_resultFlower"
            android:src="@drawable/classify_sample_flower"
            android:layout_gravity="center"
            android:layout_width="250dp"
            android:layout_height="250dp"/>

        <TextView
            android:id="@+id/tv_resultText"
            android:layout_marginTop="10dp"
            android:layout_gravity="center"
            android:gravity="center"
            android:textSize="13sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="꽃 검색을 사용해 꽃을 검색해 보세요"/>

    </LinearLayout>


    <LinearLayout
        android:layout_weight="1"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp">

        <TextView
            android:layout_margin="20dp"
            android:text="나의 기록"
            android:textSize="18sp"
            android:textColor="@color/black"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.recyclerview.widget.RecyclerView
                android:visibility="gone"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <TextView
                android:textSize="13sp"
                android:gravity="center"
                android:text="꽃 검색한 기록이 없습니다.\n 꽃 검색을 해서 새로운 기록을 남겨 보세요."
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </LinearLayout>


    </LinearLayout>

    <Button
        android:id="@+id/btn_searchFlowerCamera"
        android:textColor="@color/white"
        android:background="@drawable/title_button"
        android:layout_margin="20dp"
        android:text="꽃 검색"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

 

 

실행 결과

버튼 누르기 전

 

버튼 눌렀을 때

 

 

실행 결과에서 알 수 있듯이 별도로 텍스트 뷰의 값을 초기화 해주지 않아도 Observer를 통해서

 

관찰을 하고 있기 때문에 MainViewModel의 _name 값을 감지해서 텍스트 뷰에 값이 할당 되게 된다.

 

 

 

3. 라이브 데이터의 장점

  • UI와 데이터 상태의 일치 보장 (Observer 패턴 사용)
  • 메모리 누수 없음
  • 중지된 액티비티로 인한 비정상 종료가 없음
  • 최신 데이터 유지

 

이러한 라이브 데이터를 사용했을 때 얻을 수 있는 장점으로는 위의 4가지 장점들이 있다.

 

이중에서 메모리 누수가 없다는 장점은 라이프사이클오너가 

 

라이브 데이터와 결합되어 있기에 해당 생명주기가 종료되면 라이브데이터 객체도 자동으로 삭제되기 때문에

 

메모리 누수가 없다.

 

이러한 라이브 데이터를 사용하게 되면 위의 4가지 장점들을 사용해서 더 직관적으로 코드를 짤 수 있고

 

불필요한 코드들을 줄일 수 있다고 생각한다.

 

 

오늘의 예제 github 주소

nam-su/LiveDataExample (github.com)

 

GitHub - nam-su/LiveDataExample

Contribute to nam-su/LiveDataExample development by creating an account on GitHub.

github.com

 

'Android' 카테고리의 다른 글

제트팩 컴포즈 (Jetpack Compose)  (1) 2024.04.21
룸 (Room)  (0) 2024.04.16
뷰모델 (ViewModel)  (0) 2024.04.11
라이프 사이클 (Lifecycle)  (1) 2024.04.02
데이터 바인딩 (Data Binding)  (1) 2024.04.01