[Android] lifecycleScope vs viewLifecycleOwner.lifecycleScope

Lifecycle

Fragment의 Lifecycle

Fragment는 Activity의 lifecycle과 다르게 Fragment의 lifecycle과 Fragment의 View의 lifecycle, 두 개가 있다.

lifecycleScope vs viewLifecycleOwner.lifecycleScope

1
2
3
4
5
6
7
8
9
10
11
12
13
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

lifecycleScope.launch { // Activity가 destroy될 때까지 살아있다.
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.inputEventSharedFlow.collect { event ->
// Activity가 STARTED 이상일 때만 실행된다.
}
}
}
}
}

생명주기:

1
2
3
4
5
onCreate() ──► lifecycleScope 시작

├─ coroutine 1 (collect)

onDestroy() ──► lifecycleScope 자동 취소

생명주기 (백스택 시나리오):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
onCreateView() ──► View 생성

onViewCreated() ──► viewLifecycleOwner.lifecycleScope 시작
│ │
│ ├─ coroutine 1 (collect openEvent)
│ ├─ coroutine 2 (collect toastEvent)
│ └─ coroutine 3 (collect alertEvent)

[다른 Fragment로 이동]

onDestroyView() ──► View 파괴
viewLifecycleOwner.lifecycleScope내 모든 코루틴이 자동 취소된다.

(Fragment는 메모리(백스택)에 남아있는 상태)

[뒤로가기]

onCreateView() ──► View 다시 생성

onViewCreated() ──► 새로운 viewLifecycleOwner.lifecycleScope에서 새로운 코루틴들이 시작한다.

잘못 사용한 예

1
2
3
4
5
6
7
8
9
10
class MyFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
lifecycleScope.launch { // Fragment lifecycle
viewModel.events.collect {
// binding.textView 접근 → onDestroyView 후에도 실행됨!
binding.textView.text = "..." // 앱 크래시 가능성이 있다.
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
onCreateView() ──► View 생성

├─ lifecycleScope.launch (Fragment의 lifecycle)
│ └─ collect 시작

onDestroyView() ──► View 파괴 (binding.textView 사라짐)

│ (하지만 collect는 계속 실행 중인 상태)

└─ viewModel.events.emit() 발생
└─ binding.textView.text = "..." // 앱 크래시 가능성이 있다.

onDestroy() ──► 여기서야 lifecycleScope 내 코루틴들이 취소된다.

repeatOnLifecycle vs viewLifecycleOwner.repeatOnLifecycle

repeatOnLifecycleviewLifecycleOwner.repeatOnLifecycle도 동작 차이가 있다.

Fragment에서 사용했을 때 viewLifecycleOwner.lifecycleScope에서 launch하더라도 repeatOnLifecyclethis.repeatOnLifecycle이기 때문에 Fragment의 View 라이프사이클이 아닌 Fragment 라이프사이클을 따르기 때문에 메모리 누수 가능성이 있다.

따라서 아래와 같이 사용해야 한다.

1
2
3
4
5
6
7
8
9
10
11
class MyFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.events.collect {
binding.textView.text = "..."
}
}
}
}
}

Author

LEEJS

Posted on

2025-12-16

Updated on

2026-01-10

Licensed under

댓글