이번에는 LiveData, ViewModel, DataBinding 을 모두 사용하는 간단한 예제를 해보도록 하겠습니다.
버튼을 누르면 첫번째 TextView 에 List 에 들어있는 과일 이름 중 랜덤 값이 들어가게 되고, 두번째, 세번째 TextView 에는 그 과일 이름의 문자들이 Shuffle 된 결과가 들어가게 되는 간단한 예제 입니다.
DataBinding 을 사용하기 위해서 gradle 에 추가해줘야 합니다.
android{
...
dataBinding{
enabled = true
}
}
val testDataList: List<String> = listOf(
"apple",
"strawberry",
"pineapple",
"peach",
"grape",
"melon",
"mango"
)
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
}
}
과일 이름 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 생성시 데이터가 바로 저장 되도록 합니다.
<?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 에 사용할 변수를 지정해줍니다.
// 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 을 사용할 것을 명시적으로 알려줍니다.
<?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
해당 인프런 강의를 수강하면서 배운 내용을 토대로 정리한 글 입니다.