본문 바로가기
안드로이드(kotlin)

Navigation을 사용한 화면 이동 시 라이프사이클 변화

by 기계공학 주인장 2022. 12. 24.
반응형

Jetpack의 Navigation을 사용하여 화면 이동을 했을 때 

Activity, Fragment가 정확히 어떤 타이밍에 어떻게 lifecycle이 순환하는지 확인한다

 

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


필요한 종속 항목 선언

https://developer.android.com/jetpack/androidx/releases/lifecycle#kotlin

def lifecycle_version = "2.6.0-alpha01"
def arch_version = "2.1.0"

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// ViewModel utilities for Compose
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"

Activity

Activity에서 화면 이동을 했을 때 Acticity에서 라이프사이클이 어떻게 변화하는지 알아본다

[MainActivity의 전체 코드]

package com.example.selftest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.example.selftest.databinding.ActivityMainBinding
import kotlinx.coroutines.launch
import timber.log.Timber

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        Timber.plant(MyTimber())
        Timber.d("Activity onCreate")
        
        // lifecycleScope의 상태 변화에 따른 log 출력
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.CREATED){
                Timber.d("lifecycle Created")
            }
        }
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED){
                Timber.d("lifecycle Started")
            }
        }
        lifecycleScope.launch{
            repeatOnLifecycle(Lifecycle.State.RESUMED){
                Timber.d("lifecycle Resumed")
            }
        }
    }
    
	// Activity의 lifecycle이 변할 때마다 log 출력하기
    override fun onStart() {
        super.onStart()
        Timber.d("Activity onStart")
    }

    override fun onDestroy() {
        super.onDestroy()
        Timber.d("Activity onDestroy")
    }

    override fun onResume() {
        super.onResume()
        Timber.d("Activity onResume")
    }

    override fun onPause() {
        super.onPause()
        Timber.d("Activity onPause")
    }
}

각 lifecycle이 시작될 때 로그를 남기도록 했다

1. 처음 실행했을 때 라이프 사이클 변화

  • 기본적으로 각각의 override 함수가 먼저 호출되고 그 다음에 각각의 상태에 대한 lifecycleScope가 호출된다
  • onCreate -> onStart -> onResume

2. 현재 실행중인 앱 확인 화면(네모 버튼)으로 갔다가 돌아왔을 때 라이프 사이클 변화

  • 이 때는 lifecycle에 아무런 영향을 끼치지 않는다

3. Home 화면으로 갔다가 돌아왔을 때 라이프 사이클 변화

  • (홈으로 이동) -> onPause -> (돌아옴) -> onStart ->onResume

4. 완전히 다른 화면을 봤다가 돌아왔을 때 라이프 사이클 변화

  • onPause -> onStart -> onResume

단, 지금 코드처럼 하나의 lifecycleScope에 각각 repeatOnLifecycle로 출력한 것이 아니라 lifecycleScope.launchWhenCreated { }로 지정하면 딱 한 번만 출력한다

5. 결론

Activity의 lifecycle이 먼저 출력되고 그 다음에 lifecycleScope의 lifecycle이 출력된다


Fragment

Fragment에서 화면 이동을 했을 때 라이프 사이클의 변화를 알아본다

주로 Fragment에서 발생하는 문제는 다른 Fragment에서 돌아왔을 때 observe 하고 있던 데이터를 다시 불러와서 같은 데이터를 2번 set 하는 문제가 많다 lifecycle을 확인하고 이를 방지하기 위핸 대책을 생각해본다

테스트 과정

  1. FirstFragment, SecondFragment 이렇게 2개의 프래그먼트를 만든다
  2. FirstFragment에만 라이프 사이클을 알 수 있게 로그를 달아 놓는다
  3. FirstFragment에서 SecondFragment로 이동했다가 다시 FirstFragment로 돌아온다
  4. 돌아오는 과정에서 라이프 사이클이 어떻게 변화하는지 확인한다
  5. 프래그먼트 이동은 navigation을 사용한다

[FirstFragment의 전체 코드]

class FirstFragment : Fragment() {
    private lateinit var binding: FragmentFirstBinding
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentFirstBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Timber.d("FirstFragment onViewCreated")
        binding.nextFragment.setOnClickListener {
            val action = FirstFragmentDirections.actionFirstFragmentToSecondFragment()
            findNavController().navigate(action)
        }
    }

	// fragment의 lifecyle 변화에 따른 log 출력
    override fun onStart() {
        super.onStart()
        Timber.d("FirstFragment onStart")
    }

    override fun onResume() {
        super.onResume()
        Timber.d("FirstFragment onResume")
    }

    override fun onPause() {
        super.onPause()
        Timber.d("FirstFragment onPause")
    }

    override fun onStop() {
        super.onStop()
        Timber.d("FirstFragment onStop")
    }

    override fun onDestroy() {
        super.onDestroy()
        Timber.d("FirstFragment onDestroy")
    }
}

1. 첫 번째 프래그먼트를 열었을 때 라이프 사이클 변화

  • onViewCreated -> onStart -> onResume

2. Navigation을 사용하여 첫 번째 프래그먼트에서 두 번째 프래그먼트로 이동했을 때 라이프 사이클 변화

  • graph로 이동했을 때는 이전 fragment가 destroy되지 않고 stop 상태에 머물러 있음
  • onPause -> onStop

3. Navigation을 사용하여 두 번째 프래그먼트에서 첫 번째 프래그먼트로 돌아왔을 때 라이프 사이클 변화

  • destroy는 되지 않았지만 onViewCreated부터 다시 실행된다
  • onViewCreated -> onStart -> onResume

4. 액티비티를 완전히 닫았을 때 라이프 사이클 변화

  • Activity를 완전히 닫아야 Fragment가 Destroy된다
  • onPause -> onStop -> onDestroy


각 화면에 따른 lifecycle의 정리

  • Activity는 lifecycle이 먼저 출력되고 그 다음에 lifecycleScope의 lifecycle이 출력된다
  • Activity에서 Home 화면으로 갔다가 돌아왔을 때는 onPause -> onStart ->onResume
  • Activity에서 완전히 다른 화면을 봤다가 돌아왔을 때는 onPause -> onStart -> onResume
  • Fragment에서 Navigation을 사용하여 다른 프래그먼트로 이동했을 때는 onPause -> onStop
  • Fragment에서 Navigation을 사용하여 다시 돌아왔을 때는 onViewCreated -> onStart -> onResume
  • Fragment에서 Activity를 닫았을 때 onPause -> onStop -> onDestroy

 

안드로이드 MVVM 아키텍처란 무엇인가 필요성과 그 배경

안드로이드 MVVM 아키텍처 MVC vs MVP vs MVVM 비교 MVVM의 탄생 이유 및 필요성 MVVM 구현 방법 MVC : View와 Controller를 Activity, Fragment에서 담당 MVC 패턴의 경우 그림과 같이 View와 Controller가 연결되어 있습

android-developer.tistory.com

 

리사이클러뷰의 생명주기 분석 및 메모릭의 원인

리사이클러뷰의 라이프 사이클 (화면에 보여지기까지의 순서) onAttachedToRecyclerView - 리사이클러뷰를 화면에 붙임 onCreateViewHolder - 홀더를 생성 onBindViewHolder - 홀더와 뷰를 바인딩 onViewAttachedToWindow

android-developer.tistory.com

 

안드로이드 WorkManager는 왜 필요하고 어디서 쓰면될까?

안드로이드 코틀린 WorkManager는 어디서 사용하고 어떻게 사용하면될까? WorkManager는 왜 필요한가? 다른 백그라운드 처리들과의 차이 WorkManager는 어디에 사용하면될까? WorkManager는 어떻게 사용할 수

android-developer.tistory.com

 

안드로이드 MVVM을 사용하기 위한 필수 요소 AAC란 무엇인가?

기존에 사용하던 MVVM을 좀 더 간편하게 좀 더 정확하게 사용하기 위해 나온 것이 AAC이다. 즉, AAC란 아키텍쳐가 아니라 MVVM을 좀 더 잘 사용하기 위한 도구라고 생각하면 쉽다. 이전에 MVVM이란 무

android-developer.tistory.com

 

안드로이드 매니페스트(AndroidManifest)의 역할은 무엇일까

안드로이드 매니페스트 파일은 무엇일까? 앱 구성 요소(Activity, Broadcast, Service, Provider)를 정의한 파일 앱이 요구하는 모든 권한을 식별 앱이 요구하는 최소 API을 선언 앱에서 요구하는 하드웨어

android-developer.tistory.com

 

반응형


"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


댓글