| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 최상단
- 이미지 로딩
- 안드로이드
- layoutinflater
- Glide
- broadcast reciver
- 우아한테크코스
- 안드로이드 키보드
- 우테코 6기
- 코틀린
- 컴포즈
- 우테코
- onscrollstatechanged
- android studio
- EditText Button
- moshi
- buildSrc
- 프리코스
- coil
- compose
- constraint
- serialization
- recyclerview
- Android
- 4대 컴포넌트
- 로또 미션
- GSON
- activity
- 멀티모듈
- 안드로이드 스튜디오
- Today
- Total
정답보다 해답을
[Android] 안드로이드 Fragment Lifecycle, 알고 쓰자 본문
📑 목차
- Fragment 개요
- Fragment 생명주기 기본 개념
- Fragment와 View의 생명주기 관계
- 생명주기 콜백 메서드 상세 분석
- ViewLifecycleOwner 이해하기
- Fragment의 View Binding과 메모리 누수
- 실제 상황별 생명주기 흐름
- Fragment 개발 시 체크리스트
안드로이드 개발을 하다 보면 Fragment를 자주 사용하게 됩니다.
Fragment의 생명주기를 제대로 이해하지 못하면 메모리 누수나 크래시 같은 문제를 마주할 수 있는데요.
이번 포스팅에서는 Fragment의 생명주기에 대해 자세히 알아 보는 것을 목표로 합니다.
1. Fragment 개요
Fragment란?
Fragment는 Activity 내에서 동작하는 독립적인 UI 컴포넌트입니다.
Activity처럼 자체 생명주기를 가지고 있으며, 재사용 가능한 UI 단위입니다.
Activity와 Fragment는 수직적인 상하관계가 아닌, 수평적인 호스트-컴포넌트 관계를 가집니다.
주요 특징
- Activity 내에서 반드시 호스팅되어야 함
- 독립적인 수명 주기 보유
- Activity의 수명 주기에 직접적인 영향을 받음
- 자체 뷰 계층 구조와 생명주기 보유
2. Fragment 생명주기 기본 개념
주요 생명주기 상태
- INITIALIZED: Fragment 인스턴스 생성 상태
- CREATED: Fragment가 생성된 상태
- STARTED: Fragment가 화면에 표시될 준비가 된 상태
- RESUMED: Fragment가 사용자와 상호작용 가능한 상태
- DESTROYED: Fragment가 소멸된 상태
생명주기 흐름도
Fragment의 생명주기는 다음과 같은 순서로 진행됩니다
INITIALIZED → CREATED → STARTED → RESUMED → STARTED → CREATED → DESTROYED

3. Fragment와 View의 생명주기 관계
Fragment는 두 가지 생명주기를 동시에 관리합니다.
Fragment 자체의 생명주기
- Fragment 인스턴스의 생성부터 소멸까지 관리
- onAttach()부터 onDetach()까지
- Fragment가 백스택에 있을 때도 유지됨
Fragment View의 생명주기
- Fragment의 View 생성부터 소멸까지 관리
- onCreateView()부터 onDestroyView()까지
- View와 관련된 리소스 관리에 중요
- Fragment가 백스택에 있을 때는 View가 제거됨
두 생명주기의 차이점
- 지속 기간
- Fragment 생명주기: Fragment 인스턴스가 제거될 때까지 유지
- View 생명주기: 화면에 표시되는 동안만 유지
- 백스택에서의 동작
- Fragment: 백스택에서 유지됨
- View: 백스택에서 제거됨
- 리소스 관리
- Fragment: 전반적인 상태와 데이터 관리
- View: UI 관련 리소스 관리
4. 생명주기 콜백 메서드 상세 분석
onAttach()
Fragment가 Activity에 연결될 때 최초로 호출
override fun onAttach(context: Context) {
super.onAttach(context)
// Activity 컨텍스트 사용 가능
// 인터페이스 연결 등의 초기화 작업 수행
}
onCreate()
Fragment 초기화가 이루어지는 시점
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 상태 복원
// ViewModel 초기화
// 비-View 관련 초기화 작업
}
onCreateView()
Fragment의 View를 생성하는 시점
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// View 생성
// ViewBinding 초기화
return inflater.inflate(R.layout.fragment_example, container, false)
}
onViewCreated()
View 초기화 작업을 하기에 가장 적절한 시점
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// View 초기화
// RecyclerView 설정
// ClickListener 설정
// LiveData 관찰 시작
}
onViewStateRestored()
저장된 View의 상태가 복원되는 시점
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
// View의 상태가 복원된 후 수행할 작업
// 예: CheckBox 상태, EditText 내용 등
}
onStart()
Fragment가 사용자에게 보여질 수 있는 상태
override fun onStart() {
super.onStart()
// Fragment가 화면에 보이기 시작할 때 수행할 작업
// FragmentTransaction 가능
}
onResume()
사용자와 상호작용이 가능한 상태
override fun onResume() {
super.onResume()
// 사용자 입력 처리 시작
// 애니메이션 시작
// 실시간 업데이트 시작
}
onPause()
사용자와의 상호작용이 중지되는 시점
override fun onPause() {
super.onPause()
// 애니메이션 정지
// 실시간 업데이트 중지
// 사용자 입력 저장
}
onStop()
Fragment가 더 이상 화면에 보이지 않을 때
override fun onStop() {
super.onStop()
// 무거운 작업 중지
// 리소스 해제
}
onDestroyView()
Fragment의 View가 제거되는 시점
override fun onDestroyView() {
super.onDestroyView()
// View 관련 리소스 해제
// ViewBinding null 처리
// RecyclerView adapter null 처리
}
onDestroy()
Fragment 인스턴스가 제거되는 시점
override fun onDestroy() {
super.onDestroy()
// Fragment 관련 리소스 정리
// 코루틴 job 취소
}
onDetach()
Fragment가 Activity로부터 분리되는 시점
override fun onDetach() {
super.onDetach()
// Activity 참조 정리
// 인터페이스 연결 해제
}
5. ViewLifecycleOwner 이해하기
ViewLifecycleOwner란?
ViewLifecycleOwner는 Fragment의 View 생명주기를 관리하는
LifecycleOwner 인터페이스의 구현체입니다.
Fragment의 View가 생성될 때(onCreateView()) 생성되고,
View가 파괴될 때(onDestroyView()) 함께 파괴됩니다.
ViewLifecycleOwner vs Fragment Lifecycle
class ExampleFragment : Fragment() {
// Fragment의 생명주기
private val fragmentLifecycle = lifecycle
// View의 생명주기 (onCreateView ~ onDestroyView)
private val viewLifecycle by lazy { viewLifecycleOwner.lifecycle }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 이 시점부터 viewLifecycleOwner 사용 가능
viewLifecycleOwner.lifecycleScope.launch {
// View의 생명주기와 함께 관리되는 코루틴
}
}
}
ViewLifecycleOwner 사용이 필요한 이유
- View 생명주기와 정확한 동기화
// 잘못된 방법: Fragment lifecycle 사용
viewModel.data.observe(this) { data ->
// Fragment가 백스택에 있는 동안 계속 관찰됨
}
// 올바른 방법: ViewLifecycleOwner 사용
viewModel.data.observe(viewLifecycleOwner) { data ->
// View가 파괴되면 자동으로 구독 해제
}
- 코루틴 스코프 관리
// 잘못된 방법: Fragment lifecycle 사용
lifecycleScope.launch {
// Fragment가 백스택에 있는 동안 계속 실행됨
}
// 올바른 방법: ViewLifecycleOwner 사용
viewLifecycleOwner.lifecycleScope.launch {
// View가 파괴되면 자동으로 취소됨
}
ViewLifecycleOwner 사용 시 주의사항
- 사용 가능 시점
class ExampleFragment : Fragment() {
override fun onCreateView(...): View {
// 이 시점에서는 아직 viewLifecycleOwner 사용 불가
return inflater.inflate(R.layout.fragment_example, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 이 시점부터 viewLifecycleOwner 사용 가능
viewLifecycleOwner.lifecycleScope.launch {
// View 관련 작업
}
}
override fun onDestroyView() {
super.onDestroyView()
// 이 이후로는 viewLifecycleOwner 사용 불가
}
}
- Flow 수집 시 활용
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
// UI 업데이트
}
}
}
6. Fragment의 View Binding과 메모리 누수
Fragment View의 생명주기 특징
- Fragment의 View는 Fragment와 별도의 생명주기를 가짐
- 백스택에서 Fragment는 유지되지만 View는 제거됨
- View가 제거될 때 관련 리소스도 함께 해제되어야 함
메모리 누수가 발생하는 원인
class ExampleFragment : Fragment() {
// 잘못된 방법
private lateinit var binding: FragmentExampleBinding
override fun onCreateView(...): View {
binding = FragmentExampleBinding.inflate(inflater, container, false)
return binding.root
}
// View가 제거되어도 binding이 계속 View를 참조하고 있음
}
해결 방법: Backing Property 패턴
class ExampleFragment : Fragment() {
private var _binding: FragmentExampleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(...): View {
_binding = FragmentExampleBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // View 참조 해제
}
}
7. 실제 상황별 생명주기 흐름
Fragment 최초 생성 시
onAttach() → onCreate() → onCreateView() → onViewCreated() →
onViewStateRestored() → onStart() → onResume()
Fragment A에서 Fragment B로 전환 시 (add)
Fragment A: onPause() → onStop()
Fragment B: onAttach() → onCreate() → onCreateView() →
onViewCreated() → onViewStateRestored() →
onStart() → onResume()
Fragment A에서 Fragment B로 전환 시 (replace)
Fragment A: onPause() → onStop() → onDestroyView() →
onDestroy() → onDetach()
Fragment B: onAttach() → onCreate() → onCreateView() →
onViewCreated() → onViewStateRestored() →
onStart() → onResume()
8. Fragment 개발 시 체크리스트
1. View Binding 사용 시 주의사항
- onDestroyView()에서 반드시 binding 객체 null 처리
- Backing Property 패턴 활용
- binding 객체 전역 참조 피하기
2. Fragment 트랜잭션 관리
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.button.setOnClickListener {
parentFragmentManager.commit {
setReorderingAllowed(true)// 트랜잭션 최적화
replace(R.id.fragment_container, NextFragment())
addToBackStack(null)// 백스택 관리
}
}
}
3. Fragment 개발 체크포인트
- 생명주기 관련
- 적절한 생명주기 메서드에서 초기화 수행
- View 관련 작업은 onViewCreated()에서 처리
- 리소스 해제는 onDestroyView()에서 수행
- 상태 저장
- onSaveInstanceState()에서 중요 데이터 저장
- ViewModel 활용으로 설정 변경 대응
- 트랜잭션 관리
- commit() 대신 commitNow()는 신중하게 사용
- 트랜잭션은 적절한 생명주기 상태에서 수행
- setReorderingAllowed(true) 설정으로 최적화
참고자료
- Android Developers 공식 문서
- Fragment 생명주기 안내서
- Android Jetpack 문서
'Android' 카테고리의 다른 글
| [Android] 안드로이드 이미지 로딩 라이브러리, 알고 쓰자 (Glide, Coil, Picasso 분석하기) (0) | 2025.03.26 |
|---|---|
| [Android] Android Studio에서 SHA KEY 확인하기 (3) | 2024.12.16 |
| [Android] LayoutInflater, 알고 쓰자 - 생명주기와 View 생성 관리 (7) | 2024.11.13 |
| [Android] Google Play Console 한국어 설정 (2) | 2024.11.02 |
| [Android] Context, 알고 쓰자 (1) | 2024.10.31 |