#1 이전 글
StateFlow에 대해 다룬 이전 글에서 이어진다. LiveData가 쓰인 XML 기반 View 프로젝트를 수정해, LiveData를 StateFlow로 마이그레이션해본다.
#2 수정할 샘플 앱
위 게시글의 완성된 앱을 일부 수정해서 LiveData를 Flow로 마이그레이션시켜본다.
#3 간단한 마이그레이션 - MainActivityViewModel 수정
package com.example.implicitobservation
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import kotlinx.coroutines.flow.MutableStateFlow
class MainActivityViewModel : ViewModel() {
private var count: MutableStateFlow<Int> = MutableStateFlow(0)
fun getCurrentCount(): LiveData<Int> {
return count.asLiveData()
}
fun updateCount() {
count.value++
}
}
안드로이드 프로젝트에서 이미 LiveData를 광범위하게 사용하고 있기에, 일관성을 위해 LiveData를 유지하고 싶을 수 있다. 이 경우 아주 간단한 방식으로 마이그레이션을 할 수 있다. 바로 원래 LiveData이던 프로퍼티를 StateFlow로 바꾸고, 해당 프로퍼티의 Getter에는 asLiveData() 확장함수를 사용하는 것이다. 이러면 전체 프로젝트를 수정하지 않아도 되면서, 동시에 LiveData 대비 StateFlow의 비교 우위적 성능을 누릴 수 있다 (#1에 있는 이전글의 #4 참조). 이는 구글 공식 문서에서도, 비동기 데이터 스트림을 LiveData로 표현하고자하는 경우 권장하는 방식이다.
#4 통째로 마이그레이션
#4-1 MainActivityViewModel 수정
package com.example.livedatabasics
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
class MainActivityViewModel : ViewModel() {
private var count: MutableStateFlow<Int> = MutableStateFlow(0)
fun getCurrentCount(): StateFlow<Int> {
return count
}
fun updateCount() {
count.value++
}
}
Getter에 asLiveData()를 사용하지 않는다. 때문에, count 프로퍼티를 참조하는 코드의 수정이 필요하다.
#4-2 MainActivity 수정
package com.example.livedatabasics
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.example.livedatabasics.databinding.ActivityMainBinding
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainActivityViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
/*
viewModel.getCurrentCount().observe(this, Observer {
binding.countText.text = it.toString()
})
*/
lifecycleScope.launch {
viewModel.getCurrentCount().collect {
binding.countText.text = it.toString()
}
}
...
}
}
count는 더 이상 LiveData가 아니기 때문에, LiveData.observe()를 사용할 수 없다. 해당 코드를 삭제하고, Flow.collect()를 사용한다. collect()는 suspend가 붙는 비동기 함수이므로 CoroutineScope 내에 위치해야 한다. MainActivity는 LifecycleOwner이므로 CoroutineScope로서 (자원 효율성 증대를 위해) LifecycleScope를 사용한다.
#5 작동 확인
#2의 완성된 앱과 같이, 잘 작동한다.
#6 완성된 앱
'깨알 개념 > Android' 카테고리의 다른 글
[Android] Jetpack Compose - Side-effects (0) | 2024.09.06 |
---|---|
[Android] Jetpack Compose - Scaffold (0) | 2024.09.05 |
[Android] Jetpack Compose - StateFlow와 SharedFlow (0) | 2024.08.29 |
[Android] Coroutines Flow - Jetpack Compose에서 사용하기 (0) | 2024.08.06 |
[Android] Jetpack Compose - ViewModel에서 State 사용하기 (0) | 2024.07.23 |