Activity life Cycle 활동 수명 주기
- activity 클래스는 상태가 변경되거나 시스템이 활동을 생성, 중지 또는 재개하거나 활동이 있는 프로세스를 삭제할 때 이를 활동에 알리는 여러 콜백을 제공함.
- 사용자가 활동을 벗어났다가 다시 돌아왔을 때 활동이 작동하는 방식을 수명 주기 콜백 메서드에서 선언 가능함.
- 예 - 스트리밍 동영상 플레이어를 빌드하는 경우 사용자가 다른 앱으로 전환할 때 동영상을 일시중지하고 네트워크 연결을 종료한다면 → 사용자가 돌아오면 네트워크에 다시 연결하고 사용자가 같은 지점에서 동영상을 재개할 수 있도록 할 수 O.
수명 주기 콜백이 잘되지 않는다면 발생 가능한 문제들 :
- 앱을 사용하는 중에 전화가 오거나 다른 앱으로 전환 할 때 비정상 종료.
- 앱을 활발하게 사용하지 않는 경우 귀중한 시스템 리소스가 소비됨.
- 앱에서 나갔다가 나중에 들어왔을 때 사용자의 진행 상태가 저장되지 않음.
- 화면이 가로 방향과 세로 방향 간에 전환할 경우, 비정상 종료되거나 사용자의 진행 상태가 저장되지 않음.
활동 수명 주기 개념
- 단계 간 전환을 탐색하기 위해 Activity 클래스는 6가지 콜백으로 구성된 핵심 집합인 onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()를 제공함.
- 앱은 백그라운드에서 실행될 때 활동을 시작할 수 없음.
onCreate()
- 시스템이 먼저 활동을 생성할 때 실행되는 것으로, 필수 구현. 활동이 생성되면 생성된 상태가 됨.
onCreat() 메서드에서 활동의 전체 수명 주기 동안 한 번만 발생하는 기본 애플리케이션 시작 로직을 시작함.
onRestart()
- 액티비티가 멈췄다가 다시 시작되기 바로 전에 호출됨.
onStart()
- 액티비티가 사용자에게 보여지기 바로 직전에 호출됨.
- = 활동이 시작됨 상태로 전환되면 시스템은
onStart() 를 호출함.
- 활동이 시작됨 상태로 유지되지 않고, 콜백이 완료되면 활동이 재개됨 상태로 전환되고 시스템은 onResume() 메서드를 호출함.
onResume()
- 활동이 → “재개됨” : 포그라운드로 이동하고 시스템에서 onResume() 콜백을 호출함. 이때 앱이 사용자와 상호작용함.
- = 액티비티가 사용자와 상호작용하기 바로 전에 호출됨.
- 앱에서 포커스를 잃을 때까지 이 상태 유지함.
- 활동이 → “재개됨” : 활동의 수명 주기와 연결된 모든 수명 주기 인식 구성요소는 on_Resume 이벤트를 수신함.
- 활동이 “일시중지” → “재개됨” : 시스템은 onResume() 메서드를 다시 한번 호출함. 따라서 onResume() 를 구현하여 onPause() 중에 해제하는 구성요소를 초기화하고 활동이 “재개됨” 상태로 전환될 때마다 발생해야 하는 다른 초기화를 실행함.
onPause()
- 사용자가 활동을 떠난다는 첫 번째 신호로 이 메서드를 호출함 → 항상 활동이 소멸된다는 의미X. = 더 이상 포그라운드에 있지 않음을 나타내지만 사용자가 멀티 윈도우 모드에 있느 경우에는 계속 표시됨.
- 활동이 pause 전환되는 이유
- 멀티 윈도우 모드에서는 언제나 하나의 앱만 포커스를 가지며 시스템이 다른 모든 앱을 일시중지함.
- = 다른 액비티비가 보여질 때 호출됨. 데이터 저장, 스레드 중지 등의 처리를 하기에 적당한 메소드.
- 활동이 일시중지됨 상태로 전환되면 모든 수명 주기 인신 구성요소는 on_pause 이벤트를 수신함.
onStop()
- 활동이 사용자에게 더 이상 표시되지 않으면 “중지됨” 상태로 전환되고 시스템에서 onStop() 콜백을 호출함.
- 액티비티가 더이상 사용자에게 보여지지 않을 때 호출됨.
- 메모리가 부족할 경우에는 onStop() 메소드가 호출되지 않을 수 있음.
onDestroy()
- 액티비티가 소멸되기전에 호출됨.
- = finish() 메소드가 호출되거나 시스템이 메모리 확보를 위해 액티비티를 제거할 때 호출됨.
- 콜백 호출 이유
- 사용자가 활동을 완전히 닫았기 때문에 활동에서 finish() 가 호출되어 활동이 종료되고 있는 것.
- 기기 회전 또는 멀티 윈도우 모드 전환과 같은 구성 변경으로 인해 시스템이 일시적으로 활동을 소멸하는 경우
- 활동이 소멸됨 상태로 전환하면 ON_DESTROY 이벤트를 수신함.
- 액티비티가 다시 생성되지 않으면 ViewModel에는 onCleared() 메서드가 호출되어 소멸되기 전에 필요한 모든 데이터를 정리할 수 O.
Activity Stack
- 태스크는 어플리케이션 실행시 액티비티를 기록하는 스택.
- 스택에 각 액티비티가 열리는 순서로 정렬됨
- 액티비티를 여러개 호출 시 스택 쌓임.
- 스택에서 맨 위의 액티비티가 화면에 보임.
standard
- 후입선출 (LIFO, Last In First Out)
- 호출하는 모든 액티비티가 위에 쌓임.

singleTop
- 가장 위의 액티비티는 중복해서 쌓지 않음.

singleTask
- 쌓여있던 스택은 남아있고, 새로운 스택 공간이 하나 더 생김.

singleInstance
- 쌓여있던 스택은 남아있고, 새로운 스택 공간이 하나 더 생김.
- 새로 생긴 스택 공간에는 다른 액티비티 스택이 쌓이지 않음.
- 다른 액티비티가 호출되면 기존에 있던 스택 공간에 쌓임.
- 한 태스크의 하나의 singleInstance 액티비티만 존재 가능.

fragment lifeCycle
- 각 fragment 인스턴스에는 고유한 수명 주기가 있음.
- 사용자가 앱을 탐색하거나 앱과 상호작용 할 때 프래그먼트는 화면에서 추가 또는 삭제되거나 화면에 들어가고 나오면서 수명 주기의 여러 상태간에 전환하게 됨.
- 수명 주기를 관리하기 위해 Fragment는 LifecycleOwner 를 구현하여, getLifecycle()메서드를 통해 액세스 할 수 있는 Lifecycle 객체를 노출함.
생명주기
- 최상단으로 올라왔을 때 : CREATED - STARTED - RESUMED 순으로 진행.
- 백스택에서 pop됐을 경우 : RESUMED - STARTED - CREATED - DESTROYED
OnCreate()
- CREATED 상태라면, 프래그먼트는 FragmentManager 에 추가되고 onAttach() 메서드가 호출된 상태임.
- onCreate() 이전에 onAttach() 가 먼저 호출됨, 이 시점에서 아직 Fragment View 가 생성되지 않았음.
- onSaveInstanceState()에 의해 저장된 상태를 포함하는 savedInstanceState 파라미터는 프래그먼트가 처음 생성됐을 때만 null로 넘어오며, onSaveInstanceState() 함수를 재정의하지 않았더라도 그 이후 재생성부터는 non-null 값으로 넘어옴.
onCreateView(), onViewCreated()
- onCreateView() 의 반환값으로 정상적인 Fragment View 객체를 제공했을 때만 Fragment View의 Lifecycle 이 생성됨.
onViewStateRestored()
- 저장해둔 모든 state 값이 Fragment의 View의 계층구조에 복원됐을 때 호출됨.
- 체크 박스 위젯이 현재 체크 되어있는지 등 각 뷰의 상태값을 체크할 수 있음.
onStart()
- Fragment가 사용자에게 보여질 수 있을 때 호출됨.
- Fragment의 child FragmentManager를 통해 FragmentTransaction을 안전하게 수행 가능함.
- Fragment의 Lifecycle이 Started로 이동한 후에 Fragment View 의 Lifecycle 또한 Started로 변환됨.
onResume()
- Fragment가 보이는 상태에서 모든 Animator와 Transition 효과가 종료됨.
- 프레그먼트가 사용자와 상호작용할 수 있을 때 onResume() 콜백이 호출됨,
- Activity 의 onResume() 시점과 유사함.
- Resumend 상태가 됐다는 것이 사용자가 프래그먼트와 상호작용 하기에 적절한 상태가 됐다고 하는데, onResume()이 호출되지 않은 시점에서는 입력을 시도하거나 포커스르 설정하는 등의 작업을 임의로 함면 안된다는 것을 의미함.
onPause()
- 사용자가 Fragment를 떠나기 시작했지만 Fragment는 여전히 visible일 때 onPause()가 호출됨.
- Fragment와 View의 Lifecycle이 Paused가 아닌 Started가 됨.
onStop()
- Fragment가 더이상 화면에 보여지지 않게 되면 Fragment와 View의 Lifecycle은 Created상택 되고, onStop() 콜백 함수가 호출되게 됨.
- 부모 액티비티나 프래그먼트가 중단됐을 때 뿐만아니라 부모 액티비티나 프래그먼트의 상태가 저장될 때도 호출됨.
- API 28버넌을 기점으로 onStop()이 onSaveInstanceState() 함수보다 먼저 호출됨으로써 onStop()이 FragmentTransaction을 안전하게 수행할 수 있는 마지막 지점이 되었음.

onDestroyView()
- 모든 exit animation 과 transition이 완료되고, Fragment가 화면으로부터 벗어났을 경우 Fragment View 의 Lifecycle의 Destroyed 가 되고 onDestroy()가 호출됨.
- 가비지 컬렉터에 의해 수거될 수 있도록 Fragment View 에 대한 모든 참조가 제거되야함.
onDestroy()
- Fragment가 제거되거나 FragmentManager가 destroy 됐을 경우, 프래그먼트의 Lifecycle은 Destroyed 상태가 되고, onDestroy() 콜백 함수가 호출됨.
fragment 데이터 전달 방식
- bundle과 FragmentManager로 전달.
- Fragment Result API를 사용하여 Data 전달.
- Fragment간 공통의 ViewModel 로 전달.
- Jetpack의 Navigation에서 제공하는 safe-args 로 전달.
2. Fragment Result API를 사용하여 Data 전달.
- 예 - QR 코드를 읽고 이전 프래그먼트로 데이터를 다시 전달하는 프래그먼트가 있다면, FragmentManager는 FragmentResultOwer를 구현함, FragmentManager는 프래그먼트 결과의 중앙 저장소 역할을 할 수 있음.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setFragmentResultListener("requestKey") { requestKey, bundle ->
val result = bundle.getString("bundleKey")
}
}
- 결과를 생성하는 프래그먼트인 프래그먼트 B에서 동일한 requestKey를 사용하여 동일한 FragmentManager에 결과를 설정함. 이 작업은 setFragmentResult() API를 사용하여 실행할 수 있음.
button.setOnClickListener {
val result = "result"
setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}
3. Fragment간 공통의 ViewModel 로 전달.
- 예 - 목록을 표시하는 프래그먼트 하나와 사용자가 목록에 다양한 필터를 적용할 수 있는 프래그먼트 하나를 생각해보면, 프래그먼트가 직접 통신하면 간단하지만 그러면 더 이상 독립적이지 않음.
- ViewModel 을 공유하면 프래그먼트는 서로에 관해 알 필요가 없으며 활동은 액티비티는 통신을 용이하게 하기 위해 작업을 할 필요가 없음
class ListViewModel : ViewModel() {
val filters = MutableLiveData<Set<Filter>>()
private val originalList: LiveData<List<Item>>() = ...
val filteredList: LiveData<List<Item>> = ...
fun addFilter(filter: Filter) { ... }
fun removeFilter(filter: Filter) { ... }
}
class ListFragment : Fragment() {
private val viewModel: ListViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.filteredList.observe(viewLifecycleOwner, Observer { list ->
}
}
}
class FilterFragment : Fragment() {
private val viewModel: ListViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.filters.observe(viewLifecycleOwner, Observer { set ->
}
}
fun onFilterSelected(filter: Filter) = viewModel.addFilter(filter)
fun onFilterDeselected(filter: Filter) = viewModel.removeFilter(filter)
}
4. Jetpack의 Navigation에서 제공하는 safe-args 로 전달.
Jetpack compose Navigation 세팅
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@id/fragmentA">
<fragment
android:id="@+id/fragmentA"
android:name="com.gunt.fragmentdatapassexample.pass.passargs.fragmentA"
android:label="fragmentA" >
<action
android:id="@+id/fragmentAToB"
app:destination="@id/fragmentB"
app:launchSingleTop="true" />
<argument
android:name="argsString"
app:argType="string"
android:defaultValue=""/>
</fragment>
<fragment
android:id="@+id/fragmentB"
android:name="com.gunt.fragmentdatapassexample.pass.passargs.fragmentB"
android:label="fragmentB" >
<action
android:id="@+id/passBToA"
app:destination="@id/fragmentA"
app:launchSingleTop="true"
app:popUpTo="@id/nav_graph" />
<argument
android:name="argsString"
app:argType="string"
android:defaultValue=""/>
</fragment>
</navigation>
class FragmentA : Fragment(){
override fun onCreateView(
val args: navFragmentA by navArgs()
binding.textView.text = args.argsString
binding.btnSend.setOnClickListener {
val action = FragmentADirections.passAToB(binding.etText.text.toString())
findNavController().navigate(action)
}
}
class FragmentA : Fragment(){
override fun onCreateView(
val args: navFragmentB by navArgs()
binding.textView.text = args.argsString
binding.btnSend.setOnClickListener {
val action = FragmentADirections.passBToA(binding.etText.text.toString())
findNavController().navigate(action)
}
}
출처
[Android] 의외로 잘 모르는 Fragment 의 Lifecycle
https://velog.io/@blue-sky/Android-Fragment-to-Fragment-데이터-전달
https://developer.android.com/guide/fragments/lifecycle?hl=ko