본문 바로가기
Android Studio

[Android 앱개발 숙련] 프래그먼트 Fragment - 개념 (# 추가하기)

by 젼젼39 2024. 4. 11.

1. 프래그먼트

    : 액티비티 위에서 동작하는 모듈화된 사용자 인터페이스
    - 액티비티와 분리되어 독립적으로 동작할 수 없음

    - 여러 개의 프래그먼트를 하나의 액티비티에 조합해 창이 여러개인 UI를 구축할 수 있고, 하나의 프래그먼트를 여러 액티비티에서 재사용할 수 있음

    : 안드로이드 애플리케이션의 UI부분을 모듈화해 재사용할 수 있게 해주는 구성요소

    - 자체적인 생명주기를 가지며, 액티비티의 생명주기와 밀접하게 연결되어 있음

    = 한 개의 액티비티 화면 안에서 특정 영역만 바꿈
        (ex. 설정 화면 안에서 왼쪽 목록 중에서 누르면 우측 화면이 바뀌는...)

 

1) 프래그먼트 사용 이유

    (+) 액티비티로 화면을 계속 넘기는 것 보다는 프래그먼트로 일부만 바꾸는 것이 자원 이용량이 적어 속도가 빠름

    - 프래그먼트를 사용하면 액티비티를 적게 만들 수 있음
    - 액티비티의 복잡도를 줄일 수 있음
    - 프래그먼트를 사용하면 재사용할 수 있는 레이아웃을 분리해서 관리 가능함
    - 프래그먼트를 사용하면 최소 1개의 액티비티 안에서 프래그먼트 공간에 view만 집어넣으면 여러 액티비티를 만들지 않아도 여러 화면을 보여줄 수 있음

 

2) 프래그먼트 정의하기

    - 액티비티를 만들 때와 비슷하게, 하나의 Kotlin 소스 파일과 하나의 xml 레이아웃으로 정의

(1) Kotlin 소스 파일 생성

    -1) 프래그먼트를 생성하려면 Fragment의 서브클래스 (또는 이의 기존 서브클래스)를 생성

        - 프래그먼트에 대해 레이아웃을 제공하려면 반드시 onCreateView() 콜백 메서드를 구현해야 함

//Fragment를 상속받음
class FirstFragment : Fragment() {
    //콜백메소드 구현
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        //inflate함수를 통해 
        // fragment_first라는 레이아웃 파일을 FirstFragment라는 클래스에서 쓰겠다는 것
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    // inflate() 함수를 통해 fragment_first.xml 파일로부터 레이아웃을 로드

(2) xml 레이아웃 생성

        - 프래그먼트도 부분 화면이므로 화면에 표시될 뷰들을 정의하는 xml 파일을 /res/layout 폴더 안에 생성하기

 

3-1) 프래그먼트를 액티비티의 레이아웃 파일에 정적 추가하는 방법

    : 프래그먼트를 액티비티의 레이아웃 파일 안에서 선언

        - <fragment> 안의 android:name 특성은 레이아웃 안에서 인스턴스화할 Fragment 클래스를 지정함

        * 각 프래그먼트에는 액티비티가 재시작되는 경우 프래그먼트를 복구하기 위해 시스템이 사용할 수 있는 고유한 식별자가 필요함

        -> 프래그먼트에 id를 제공하는 방법
        1) 고유한 id와 함께 android:id 속성을 제공
        2) 고유한 문자열과 함께 android:tag 속성을 제공
        3) (위의 두 가지 중 어느것도 제공하지 않으면) 시스템은 컨테이너 뷰의 id를 사용함

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <fragment
        //name에는 패키지 경로와 이름 지정...
        android:name="com.skmns.fragmentbasic.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/fragment" />
</LinearLayout>

 

            

3-2) Kotlin 코드에서 동적으로 프래그먼트 추가하는 방법 : supportFragmentManager

supportFragmentManager.commit {
            //어떤 프레임 레이아웃에 띄울것인지, 어떤 프래그먼트인지.
            // 여기에선 frameLayout 레이아웃에 frag 프래그먼트를 띄울 것임
            replace(R.id.frameLayout, frag)
            setReorderingAllowed(true)
            addToBackStack("")
        }
- supportFragmentManager - 사용자 상호작용에 응답해
     Fragment를 추가하거나 삭제하는 등 작업을 할 수 있게 해주는 매니저
- replace - 어느 프레임 레이아웃에 띄울것인가, 어떤 프래그먼트인가
- setReorderingAllowed - 애니메이션과 전환이 올바르게 작동하도록
     트랜젝션과 관련된 프래그먼트의 상태 변경을 최적화
- addToBackStack - 뒤로가기 버튼 클릭 시 다음 액션 (이전 프래그먼트로 가는지, 앱이 종료되는지)

 

<비교>

  동적으로 추가 정적으로 추가
프래그먼트 정의 Kotlin 코드로 프래그먼트 클래스 작성 xml 레이아웃 파일에 직접 정의
액티비티 레이아웃 파일 레이아웃 파일에 빈 컨테이너 뷰 추가 프래그먼트를 포함한 xml 레이아웃 추가
액티비티에서 추가 방법 프래그먼트 관리자를 사용해 프래그먼트 트랜잭션을 시작하고 추가 xml 레이아웃에 직접 <fragment> 태그 추가
MainActivity.kt 파일 supportFragmentManager 사용 x
코드 예시 <FrameLayout /> <fragment />

 

 

2. 액티비티 vs 프래그먼트

1) 액티비티 : 시스템의 액티비티 매니저에서 인텐트를 해석해 액티비티간 데이터를 전달

                    // 화면에 나타나는 한 장의 화면...
                    // 액티비티 여러개를 만들어 intent를 통해 다른 액티비티 호출...

2) 프래그먼트 : 액티비티의 프래그먼트 매니저에서 메소드로 프래그먼트간 데이터를 전달

                        // 한 개의 액티비티 안에 특정 영역을 만들어두고 프래그먼트 매니저를 통해 전환하는 것.

 

 

3. 프래그먼트 생명주기

    (+) 프래그먼트의 생명주기를 이해하는 것은 안드로이드 앱을 효율적으로 관리하고, 사용자에게 부드러운 인터페이스 경험을 제공하는 데 중요함

    - 각 단계에서는 프래그먼트의 생명주기에 맞춰 적절한 작업을 수행해 메모리 누수를 방지하고, 애플리케이션의 성능을 최적화할 수 있음

1. onAttach() - 프래그먼트가 액티비티에 연결될 때 호출됨
- 이 시점에서 프래그먼트는 액티비티와 아직 완전히 연결되지는 않은 상태
2. onCreate() - 프래그먼트가 생성될 때 호출됨
- 초기화 작업, 리소스 바인딩 등을 수행할 수 있음
3. onCreateView() - 프래그먼트의 레이아웃을 인플레이트하는 곳
- 뷰를 생성하고, 레이아웃을 설정함
// onViewCreated() - Fragment의 뷰가 만들어진 직후 호출됨
- 주로 UI 관련 작업을 수행할 때 사용됨
4. onActivityCreated() - 액티비티의 onCreate() 메서드가 완료된 후 호출됨
- 액티비티와 프래그먼트의 뷰가 모두 생성된 상태이므로, 뷰와 관련된 초기화를 수행
5. onStart() - 프래그먼트가 사용자에게 보여질 준비가 되었을 때 호출됨
- 필요한 리소스를 할당하거나, 애니메이션을 시작할 수 있음 
6. onResume() - 프래그먼트가 사용자와 상호작용할 수 있는 상태가 되었을때 호출됨
- 프래그먼트가 포그라운드에 있을 때 실행되는 작업을 여기서 처리함 
7. onPause() - 프래그먼트가 일시정지될 때 호출됨
- 상태 저장, 스레드 중지 등의 작업을 수행함
8. onStop() - 프래그먼트가 더 이상 사용자에게 보이지 않을 때 호출됨
- 리소스 해제, 스레드 정지 등을 수행함
9. onDestroyView() - 프래그먼트의 뷰와 관련된 리소스를 정리할 때 호출됨
10. onDestroy() - 프래그먼트가 파괴될 때 호출됨
- 프래그먼트의 상태를 정리하고, 모든 리소스를 해제함
11. onDetach() - 프래그먼트가 액티비티로부터 분리될 때 호출됨
- 프래그먼트가 액티비티와의 모든 연결을 해제함