[MVVM 패턴 공부] LiveData + ViewModel + DataBinding 간단한 예제

LeeEunJae·2022년 9월 18일
0

Study Kotlin

목록 보기
16/20

이번에는 LiveData, ViewModel, DataBinding 을 모두 사용하는 간단한 예제를 해보도록 하겠습니다.

📌 실행 결과

버튼을 누르면 첫번째 TextView 에 List 에 들어있는 과일 이름 중 랜덤 값이 들어가게 되고, 두번째, 세번째 TextView 에는 그 과일 이름의 문자들이 Shuffle 된 결과가 들어가게 되는 간단한 예제 입니다.

📌 의존성 추가

DataBinding 을 사용하기 위해서 gradle 에 추가해줘야 합니다.

android{
	...
    
    dataBinding{
    enabled = true
	}
}

📌 과일 이름 List

val testDataList: List<String> = listOf(
    "apple",
    "strawberry",
    "pineapple",
    "peach",
    "grape",
    "melon",
    "mango"
)

📌 ViewModel


import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel

class MainViewModel : ViewModel() {

    private var _mutableWord = MutableLiveData("")
    val liveWord: LiveData<String>
        get() = _mutableWord

    private var _randomMutableWord = MutableLiveData("")
    val randomLiveWord: LiveData<String>
        get() = _randomMutableWord

    val newData = Transformations.switchMap(liveWord){
        getRandomWordShuffled(it)
    }

    init{
        getNextData()
    }

    fun getNextData(){
        val currentWord = testDataList.random()
        val randomWord = currentWord.toCharArray()
        randomWord.shuffle()

        _mutableWord.value = currentWord
        _randomMutableWord.value = String(randomWord)
    }

    fun getRandomWordShuffled(word: String): MutableLiveData<String>{
        val liveData = MutableLiveData("")
        val randomTextWord = word.toCharArray()
        randomTextWord.shuffle()

        liveData.value = String(randomTextWord)
        return liveData
    }
}

ViewModel 코드 설명

과일 이름 List 에서 랜덤으로 값을 가져와 저장하기 위한 LiveData 변수 입니다.

private var _mutableWord = MutableLiveData("")
    val liveWord: LiveData<String>
        get() = _mutableWord

LiveData 는 MutableLiveData 와 LiveData 로 나뉩니다.
MutableLiveData 는 수정 가능한 데이터 홀더 클래스이고, LiveData 는 수정이 불가능합니다.
그래서 ViewModel 에서는 데이터를 변경해주기 위해서 MutableLiveData 를 사용하고,
LiveData 는 다른 곳에서 데이터를 사용하기 위해서 사용합니다.

LiveData 로 선언한 변수에 getter 를 구현해서 다른곳에서 데이터를 get 할 때, MutableLiveData 의 값을 리턴하게 합니다.

fun getNextData(){
        val currentWord = testDataList.random()
        val randomWord = currentWord.toCharArray()
        randomWord.shuffle()

        _mutableWord.value = currentWord
        _randomMutableWord.value = String(randomWord)
    }

리스트에서 랜덤 값을 뽑아 currentWord 에 저장하고, MutableLiveData 값을 업데이트 합니다.
randomWord 에는 랜덤으로 생성된 과일 이름을 shuffle 한 결과가 저장되고, 마찬가지로 MutableLiveData 값을 업데이트 합니다.

fun getRandomWordShuffled(word: String): MutableLiveData<String>{
        val liveData = MutableLiveData("")
        val randomTextWord = word.toCharArray()
        randomTextWord.shuffle()

        liveData.value = String(randomTextWord)
        return liveData
    }

리스트 랜덤 값을 word 라는 인자로 받고, suffle 한 결과를 MutableliveData 를 생성해서 값을 넣은 후, 그 MutableLiveData를 리턴하는 메서드 입니다.
이 메서드는 SwitchMap 을 사용해보기 위해서 구현한 것입니다.

val newData = Transformations.switchMap(liveWord){
        getRandomWordShuffled(it)
    }

    init{
        getNextData()
    }

Transformations.switchMap 을 사용해서 인자로 liveWord 를 넣고, 위에서 구현한 메서드를 호출 합니다.
생성자에서 getNextData() 를 호출해서 ViewModel 생성시 데이터가 바로 저장 되도록 합니다.

📌 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">

    <data>
        <variable
            name="vm"
            type="com.dldmswo1209.jetpackstudy.MainViewModel" />
    </data>

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:textSize="50sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:textSize="50sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:textSize="50sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@+id/nextButton"
            android:text="next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>


    </androidx.appcompat.widget.LinearLayoutCompat>
</layout>

MainActivity 에서 DataBinding 을 사용하기 위해서 우선 activity_main.xml 의 전체 코드를 layout 태그로 감싸줘야 합니다.
그리고 data 태그를 사용해서 DataBinding 에 사용할 변수를 지정해줍니다.

📌 MainActivity.kt

// LiveData + DataBinding + ViewModel
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var viewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        viewModel = ViewModelProvider(this)[MainViewModel::class.java]

        binding.vm = viewModel
        binding.lifecycleOwner = this

        binding.nextButton.setOnClickListener {
            viewModel.getNextData()
        }
    }

}

binding.vm = viewModel 로 vm 이라는 변수에서 viewModel 을 사용할 것을 명시적으로 알려줍니다.

📌 activity_main.xml 전체 코드

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">

    <data>
        <variable
            name="vm"
            type="com.dldmswo1209.jetpackstudy.MainViewModel" />
    </data>

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:text="@{vm.liveWord}"
            android:textSize="50sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:text="@{vm.randomLiveWord}"
            android:textSize="50sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:text="@{vm.newData}"
            android:textSize="50sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@+id/nextButton"
            android:text="next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>


    </androidx.appcompat.widget.LinearLayoutCompat>
</layout>

Activity 에서 vm 변수에서 ViewModel 을 사용할 것을 명시적으로 지정해줬기 때문에 이곳에서 ViewModel 에 있는 데이터를 사용할 수 있게 되었습니다.

@{vm.liveWord} 를 TextView 의 text 로 지정해줘서 DataBinding 을 해줍니다.

👀 출처 및 참고자료

https://www.inflearn.com/course/%EC%B9%9C%EC%A0%88%ED%95%9C-jetpack-1/dashboard
해당 인프런 강의를 수강하면서 배운 내용을 토대로 정리한 글 입니다.

profile
매일 조금씩이라도 성장하자

0개의 댓글