BackUp (관리중지)/Android 실습

Fragment LifeCycle 실습 with Activity

devhyeon0312 2021. 4. 23. 01:33

안녕하세요, DevHyeon 입니다.

오늘은 Fragment 이론에서 학습한 내용에 대해서 실습을 통해 직접 알아보도록 하겠습니다.

Fragmnet LifeCycle 이론 바로가기


fragment 를 삽입하는 2가지 방법을 실습해 볼것입니다.

a. Layout.xml 에서 <fragment> 요소로 삽입하는 방법

b. Code 를 사용하여 기존의 ViewGroup 에 추가하여 Layout 에 삽입하는 방법

 

생명주기는 총 2가지 테스트를 통해서 확인을 해볼겁니다.

c. Actvity 에서 생성된 Fragment 가 Activity 생명주기에 따라 어떻게 변하는가?

d. Activity 에서 생성된 Fragment 가 Activity 는 Running 상태를 유지하고 있을 때, 변화되는 상황의 Fragment 의 생명주기 알아보기


1. Fragment 삽입 실습

사전작업

1.  Fragment 에 사용되는 layout.xml 만들기 :) [ UI 가 필요없는 Fragment 의 경우 생략 가능합니다. ]

// UI 가 필요없는 Fragment 는 생략 가능합니다. 기억하시죠? Fragment 는 동작 or UI 로 사용된다는거~

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sample Fragment"
        android:textSize="32sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

2. Fragment를 상속받은 나만의 Fragment 클래스 만들기 :)

//저는 ViewBinding 을 사용하여 작성한 코드입니다!

class SampleFragment : Fragment() {
    private var _binding: FragmentSampleBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSampleBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}

 

 

a. Layout.xml 에서 <fragment> 요소로 삽입하는 방법
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/fragment3"
        android:name="com.devhyeon.fragmentlifecycle.fragments.SampleFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

<fragment> 속성에 tools:layout="@layout/fragment_sample"  를 추가하여 미리 확인해볼 수 있어요.

추가하기 전

tools:layout="@layout/fragment_sample" 추가 전

tools:layout="@layout/fragment_sample" 추가 후

 

b. Code 를 사용하여 기존의 ViewGroup 에 추가하여 Layout 에 삽입하는 방법

1. fragment 가 Activity 에서 삽입될 수 있는 ViewGroup 을 xml 에 추가해주어야 합니다. (id 는 필수~)

 * FrameLayout 뿐만 아니라, 다른 ViewGroup 인 Constraint, Linear, Table 이런 Layout 을 사용할 수도 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/frameSample"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

2. Fragment 를 삽입하는 코드 작성

class SampleActivity : AppCompatActivity() {
    lateinit var binding : ActivitySampleBinding
    companion object {
        private val TAG = "DevHyeon : " + SampleActivity::class.java.name
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        println("$TAG : onCreate()")
        /** ViewBinding 의 코드이므로, Fragment LifeCycle Test 에 직접적인 연관이 없습니다. */
        binding = ActivitySampleBinding.inflate(layoutInflater)
        setContentView(binding.root)

		/** Fragement 삽입 코드 */
        if (savedInstanceState == null) {
            supportFragmentManager
            	.beginTransaction()
                .add(binding.frameSample.id, BodyFragment())
                .commit()
        }
    }
}

이렇게하면, Activity 가 onCreate() 되는 시점에 삽입이 가능합니다 :)

 


2. 생명주기 확인 실습

c. Activity 에서 생성된 Fragment 는 Activity 생명주기에 따라 어떻게 변하는가?

Activity 의 생성부터 파괴까지 일어나는 로그

Activity 실행

1. 액티비티 생성                        👉 Activity onCreate()

2. 프래그먼트 생성                    👉 Fragment onAttach() ~ onViewStateRestored()

3. 프래그먼트 실행                    👉 Fragment onStart()

4. 액티비티 실행                        👉 Activity onStart()

5. 액티비티 run상태                   👉 Activity onResume()
6. 프래그먼트 run상태                👉Fragment onResume()

 

Activity 정지

7. 프래그먼트 상호작용 불가        👉 Fragment onPuase()

8. 액티비티 상호작용불가            👉 Activity onPuase()

9. 프래그먼트 정지                      👉 Fragment onStop()

10. 액티비티 정지                        👉 Activity onStop()

11. 프래그먼트 상태저장               👉 Fragment onSaveInstanceState()

 

Activity 재실행

12. 액티비티 재실행                     👉 Activity onRestart()

13. 프래그먼트 실행                    👉 Fragment onStart()

14. 액티비티 실행                        👉 Activity onStart()

15. 액티비티 run상태                   👉 Activity onResume()
16. 프래그먼트 run상태               👉Fragment onResume()

 

Activity 종료

17. 프래그먼트 상호작용 불가      👉 Fragment onPuase()

18. 액티비티 상호작용불가         👉 Activity onPuase()

19. 프래그먼트 정지                   👉 Fragment onStop()

20. 액티비티 정지                     👉 Activity onStop()

21. 프래그먼트 파괴                   👉 Fragment onDestroyView() ~ onDestroy() 

22. 액티비티 파괴                     👉 Activity onDestroy()

 

Activity 생성 이후에 onPuase(사용자와의 상호작용 불가) 부터 onResume(사용자와의 상호작용 가능) 까지의 로그

Activity 실행

1. 액티비티 생성                         👉 Activity onCreate()

2. 프래그먼트 생성                     👉 Fragment onAttach() ~ onViewStateRestored()

3. 프래그먼트 실행                     👉 Fragment onStart()

4. 액티비티 실행                        👉 Activity onStart()

5. 액티비티 run상태                    👉 Activity onResume()
6. 프래그먼트 run상태                👉Fragment onResume()

 

Activity 와 사용자 상호작용 불가

7. 프래그먼트 상호작용 불가        👉 Fragment onPuase()

8. 액티비티 상호작용불가            👉 Activity onPuase()

 

Activity 와 사용자 상호작용 가능

9. 액티비티 run상태                    👉 ActivityonResume()
10. 프래그먼트 run상태                👉FragmentonResume()

 

 

* 핵심포인트 :

Running 단계로 가는 과정에서는 Fragment LifeCycle 이후에 Activity 의 다음 LifeCycle 이 동작합니다.

Destroy 단계로 가는 과정에서는 Activity LifeCycle 이후에 Fragment 의 다음 LifeCycle 이 동작합니다.

 

이해가 어렵나요? 저는 이렇게 생각했습니다.

Activity 에 Fragment 를 보여줘야 하는 과정에서 Fragment 가 먼저 준비되지 않으면 Activity 는 찰나의 순간에 아무것도 보여주지 않는다.

Activity 를 제거해야하는 과정에서 Fragment 를 먼저 제거하면, Activity 는 찰나의 순간에 아무것도 보여주지 않는다.

 

어떤가요?  사용자를 중점으로 생각해보면 조금더 와닿을수도..

 

d. Activity 에서 생성된 Fragment 가 Activity 는 Running 상태를 유지하고 있을 때, 변화되는 상황의 Fragment 의 생명주기 알아보기

Activity 가 onResume() 까지 진행 한 이후에

Fragment 를 삽입하게 되면, Fragment LifeCycle 이 onResume() 까지 동작하는 것을 알 수 있습니다.

 

 

오늘의 결론

Fragment 와 Activity 에서 엮이는 LifeCycle 이 생각보다 복잡하기 때문에, 한번쯤은 직접 확인해보는게 좋을 것 같습니다.

Fragment LifeCycle 은 직접 실행시켜보고 로그를 확인해보는것이 좀더 빠른 이해를 도울 수 있습니다.

 

아래는 테스트에 사용한 코드원본입니다.

github.com/DevHyeon0312/Fragment-LifeCycle-with-Activity

 

 

❤️ 별거 없는 내용일지라도, 공감과 Star 하나하나가 저에게는 성취감이 됩니다! ❤️