# Table of Contents

# LiveData

LiveData는 관찰 가능한 데이터입니다. LiveDatavalue라는 속성에 데이터를 유지하고 있으며, 이 데이터의 값이 변경되면 관찰자에게 통지됩니다.

# LiveData 사용법

LiveData는 다음과 같이 생성합니다.

private val count: LiveData<Int> by lazy { LiveData<Int>() }

LiveData는 값을 변경할 수 없습니다. 따라서 변경이 필요하다면 MutableLiveData를 사용합니다.

private val count: MutableLiveData<Int> by lazy { MutableLiveData<Int>() }

초기값은 다음과 같이 설정합니다.

private val count: MutableLiveData<Int> by lazy { MutableLiveData<Int>().apply { value = 0 } }

# LiveData 관찰

이렇게 선언된 MutableLiveData는 액티비티에서 다음과 같이 관찰할 수 있습니다.

class MainActivity: AppCompatActivity() {

    // ..

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // MutableLiveData 관찰
        count.observe(this) { count ->
            // MutableLiveData 값이 변하면 이 부분이 호출
        }
    }
}

프래그먼트에서는 다음과 같이 관찰할 수 있습니다.

class MainFragment: Fragment() {

    // ..

    override fun onViewCreated() {

        // MutableLiveData 관찰
        count.observe(viewLifecycleOwner) { count ->
            // MutableLiveData 값이 변하면 이 부분이 호출
        }        
    }
}

# LiveData 변경

MutableLiveDatavalue속성을 사용하여 값을 변경할 수 있습니다.

private val count: MutableLiveData<Int> by lazy { MutableLiveData<Int>().apply { value = 0 } }

// 값을 1로 변경
count.value = 1

# ViewModel과 함께 사용하기

LiveDataViewModel과 함께 빈번하게 사용됩니다. 아래 예제는 ViewModelLiveData를 사용하여 구현한 카운터 앱입니다.

// MainViewModel.kt
class MainViewModel : ViewModel() {

    private val _liveCount: MutableLiveData<Int> by lazy { MutableLiveData<Int>().apply { value = 0 } }
    val liveCount: LiveData<Int> get() = _liveCount

    fun plus() {
        _liveCount.value = _liveCount.value?.plus(1)
    }

    fun minus() {
        _liveCount.value = _liveCount.value?.minus(1)
    }

}
// MainActivity.kt
class MainActivity : AppCompatActivity() {

    private lateinit var mainViewModel: MainViewModel

    private val textViewValue: TextView by lazy { findViewById(R.id.activity_main_tv_value) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // ViewModel 초기화
        mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        // LiveData 관찰
        mainViewModel.liveCount.observe(this) {
            textViewValue.text = it.toString()
        }
    }

    fun onButtonClicked(view: View) {
        when(view.id) {
            R.id.activity_main_btn_plus -> {
                mainViewModel.plus()
            }
            R.id.activity_main_btn_minus -> {
                mainViewModel.minus()
            }
        }
    }
}

# setValue(), postValue()

MutableLivevalue속성을 사용하면 값을 변경할 수 있습니다.

private val count: MutableLiveData<Int> by lazy { MutableLiveData<Int>().apply { value = 0 } }

// 값을 1로 변경
count.value = 1

value속성을 사용하면 내부적으로 setValue()메소드가 호출됩니다. 아래 코드는 동일합니다.

count.value = 1
count.setValue(1)

setValue()는 메인 스레드에서 값을 변경할 때 사용합니다. 반면 postValue()는 작업 스레드에서 값을 변경할 때 사용합니다. 다음 예제는 코루틴에서 postValue()를 호출하는 예제입니다.

// MainViewModel.kt
class MainViewModel : ViewModel() {

    private val _liveCount: MutableLiveData<Int> by lazy { MutableLiveData<Int>().apply { value = 0 } }
    val liveCount: LiveData<Int> get() = _liveCount

    fun plus() {
        viewModelScope.launch(Dispatchers.IO) {
            // 작업 스레드에서 값을 변경
            _liveCount.postValue(_liveCount.value?.plus(1))
        }
    }

    fun minus() {
        // 메인 스레드에서 값을 변경
        _liveCount.value = _liveCount.value?.minus(1)
    }
}