viewLifecycleOwner.lifecycleScope.launch {}를 사용하여 Fragment의 수명 주기에 연결된 코루틴을 사용하여 Flow를 사용하면, 이lifeCycle의 수명주기를 인식을 못한다는 단점이 있다
따라서 lifecycleScope.launchWhenCreated를 사용하여, lifeCycle의 수명주기를 인식하도록 해줄수있다
아래는 공식문서에 나온 설명이다
launchWhenStarted는 이 LifecycleCoroutineScope를 제어하는 수명 주기가 최소한 Lifecycle.State.STARTED 상태일 때 지정된 블록을 시작하고 실행합니다.
반환된 Job은 Lifecycle이 폐기되면 취소됩니다.
즉, launchWhenCreated는 수명 주기가 STARTED 또는 RESUMED 상태가 아닐 때 코루틴 실행을 일시 중지한다. 이는 수명 주기가 다시 활성화될 때까지 코루틴이 작업을 수행하거나 리소스를 낭비하지 않음을 의미한다
이렇게 하면 불필요한 작업, 메모리 누수 또는 앱 충돌을 방지하는 데 도움이 될 수 있다
그치만 launchWhenCreated는 이제 deprecated되었다 -> 경우에따라 자원낭비로 이어질수도 있기 때문
(launchWhenStarted뿐만 아니라 다른 launchWhenX (launchWhenResumed, launchWhenCreated) 기능도 이제 더 이상 사용되지 않게되었다)
private fun observeViewModel(){
lifecycleScope.launchWhenCreated {
mapViewModel.regionSearch.collectLatest{
Log.d("it_data", it.toString()) // SearchResponse 전체가져옴
// 검색결과에 documents가 포함되어있으면(무조건 포함함), 그 documents값중 첫번쨰값을 가져옴
it?.documents?.firstOrNull()?.let { document ->
Log.d("documents__",document.toString()) // SearchDocumentsResponse의 첫번째값 가져옴
setMapData(document)
}
}
}
}
기존 코드
따라서 launchWhenCreated를 대체할기능으로 구글은 Lifecycle.repeatOnLifecycle API를 사용할 것을 권장한다
따라서 repeatOnLifecycle을 사용한 기본 예제를 봐보자
// lifecycleScope에서 새 코루틴을 만듭니다.
lifecycleScope.launch {
// RepeatOnLifecycle은 수명 주기가 STARTED 상태에 있을 때마다 // 새 코루틴에서 블록을 시작하고 STOPPED일 때 취소합니다.
RepeatOnLifecycle(Lifecycle.State.STARTED) {
// 값 수신을 시작합니다.
// 이는 수명 주기가 시작되고
수집이 중지될 때 발생합니다. // 수명 주기가 중지되면 수집이
viewModel.dataFlow.collect {
// 수집된 값으로 일부 작업을 수행합니다.
}
}
}
repeatOnLifecycle 사용
repeatOnLifecycle은 권장되는 두가지 방법이 있는데
1. 단일흐름을 수집해야하는 경우는 flowWithLifecycle() 를 사용해서 구현할 수 있다
viewLifecycleOwner.lifecycleScope.launch {
myViewModel.getDataFlow()
.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED)
.collect {
// 수집된 값으로 일부 작업을 수행합니다.
}
}
단일흐름
2. 여러 흐름을 병렬로 수집해야 하는 경우 RepeatOnLifecycle을 사용해서 구현할 수 있다
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
// 병렬로 여러 흐름을 수집합니다.
launch {
myFlow1.collect {
// 수집된 값으로 일부 작업을 수행합니다.
}
}
launch {
myFlow2.collect {
// 수집된 값으로 일부 작업을 수행합니다.
}
}
}
}
병렬
나는 아까 launchWhenCreated를 사용하여 구현했던 코드를
repeatOnLifecycle를 사용해서 수정해봤다
구현해야하는 사항은 단일흐름이기 때문에 flowWithLifecycle()를 사용해서 수정해주었다!!
private fun observeViewModel(){
viewLifecycleOwner.lifecycleScope.launch {
mapViewModel.regionSearch.flowWithLifecycle(viewLifecycleOwner.lifecycle, STARTED).collectLatest {
Log.d("it_data", it.toString()) // SearchResponse 전체가져옴
it?.documents?.firstOrNull()?.let { document ->
Log.d("documents__",document.toString()) // SearchDocumentsResponse의 첫번째값 가져옴
setMapData(document)
}
}
}
}
단일흐름을 사용한 flowWithLifecycle() 로 수정한 코드
# 참고자료
Launching Coroutines, Collecting Flow with Lifecycle scope in a correct way
Coroutines have become very popular among Android developers in recent years, as they offer a simpler and more concise way to write…
medium.com
https://medium.com/jaesung-dev/launchwhenx-api-deprecated-%EC%84%9C%EC%82%AC-16c81e1a1073
launchWhenX API Deprecated 서사
(Release Note) androidx.lifecycle 2.6.0-alpha04
medium.com
'개발 노트 > Kotlin' 카테고리의 다른 글
[안드로이드 스튜디오 SDK 에러] SDK location not found. (0) | 2024.08.03 |
---|---|
[Android/Kotlin] 프래그먼트간 데이터를 공유하는 ViewModel (0) | 2024.06.05 |
[Android] 로그캣 오류가 세로로 뜨는 이상한 문제 (0) | 2024.05.31 |
[Android/Kotlin]Kakao 주소검색 API 사용해서, 지도에서 지역검색 데이터 받아오기 (0) | 2024.05.30 |
[Android/Kotlin] KakaoMap 주소 검색 API [HTTP 401에러] (0) | 2024.05.29 |