Tech Log

[Android] Fragment 본문

Android/etc

[Android] Fragment

yuhee kim 2022. 6. 1. 21:12

클론 코딩을 하다가 Fragment를 그닥 깊게 생각하지 않고 써왔다. 그러다가 Fragment 용례가 기억이 안나서 다시 찾아보게 되었다.

Fragment의 이론 내용을 공부하는 중, 몰랐던 내용이 많아 정리해보고자 한다.

 

1.  배경

 

출처 : Android Developers(https://developer.android.com/guide/components/fragments?hl=ko)

 

태블릿과 같이 큰 화면이 나오면서, 안드로이드 UI에도 유연성이 요구되었다. 기존의 핸드폰과 같이 작은 화면만 다루었을 때는, Activity 단위로 UI를 구성해도 수월했다. 태블릿의 화면은 핸드폰의 화면보다 훨씬 크기 때문에, UI 구성 요소를 사용할 공간이 더 많다. 따라서 Activity의 레이아웃을 나누자는 아이디어가 나오게 되었다.

기존의 레이아웃들로 Activity를 구분지어도 되지만, Dynamic한 동작(디바이스에 따라 View 감추기, 보이기, 위치 이동)을 처리하기에는 번거로웠다. 기존의 레이아웃을 사용해서 Activity를 구성할 경우, 매우 복잡한 UI 구성한 요소를 가지게 될 수 있다. 반면, Fragment로 나누게 되면, 모듈 단위로 Activity를 나누어 쉽게 관리할 수 있게 된다.

Fragment로 Activity를 나누게 되면, 런타임 내에 Activity의 UI를 쉽게 수정할 수 있다. 또한, 이러한 변경 내용을 Activity가 관리하는 백 스택에 보관할 수 있다. 한 번 작성된 Fragment는 재사용이 가능하도록 디자인이 수월하다.

 

2. 특징

  • 자체적인 생명 주기를 갖고 있다(Fragment 생명주기에 대한 포스팅은 여기)
  • 자체 입력 이벤트를 수신할 수 있다
  • 하나의 Fragment를 여러 Activity에서 재사용
  • "하위 Activity"와 같은 개념
  • 다른 Activity나 다른 Fragment를 직접 조작하는 로직을 포함해서는 안된다(모듈성, 재사용성을 해치게 된다)
  • 항상 Activity 내에서 호스팅 되어야 한다
    • 따라서 Fragment의 생명 주기는 호스트 Activity의 생명 주기에 직접적으로 영향 받는다
    • Activity가 일시정지되는 경우, 그 안의 모든 Fragment도 일시정지

 

3. 사용 방법

1-1. Activity의 레이아웃 파일에 Fragment 요소를 추가(android:name 속성에 이후에 추가할 Fragment 클래스 파일의 이름을 지정해 넣는다)

 

1-2. 혹은 FragmentManager을 사용해서 Fragment를 Activity 내에서 사용 (Activity가 실행 중이라면 언제든지 Fragment를 추가할 수 있다)

 

2. Fragment에 적용할 레이아웃 파일(.xml) 생성

 

3. Fragment 클래스 파일 생성(Fragment를 상속받는 클래스 파일이다)

 

4. Fragment 레이아웃 파일과 클래스 파일을 View Binding으로 연결(혹은 Fragment 클래스 파일에서 inflate에 지정하여 연결)

 

5. 호스팅 Activity 클래스에서 Fragment 클래스를 인스턴스화시킨다 (1-2만 해당)

 

6. FragmentTransaction을 사용하여 Fragment를 제어한다

예시)

supportFragmentManager.beginTransaction()

 

4. 실습

1-1. Activity의 레이아웃 파일에 Fragment 요소를 추가(android:name 속성에 이후에 추가할 Fragment 클래스 파일의 이름을 지정해 넣는다)

아래는 호스팅 Activity의 레이아웃 파일이다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>

 

1-2. 혹은 FragmentManager을 사용해서 Fragment를 Activity 내에서 사용 (Activity가 실행 중이라면 언제든지 Fragment를 추가할 수 있다)

이 방법은 기존의 ViewGroup에 Fragment를 추가하는 방식이다.

FragmentTransaction을 사용해서 Fragment를 제어하는 방식이기도 하다.

add() 메소드를 사용해서 Fragment를 ViewGroup에 쉽게 추가할 수 있다.

해당 방법은 Activity가 실행 중일 때, Fragment를 추가시킬 수 있는 방법이다.

대신 호스팅 Activity에 FrameLayout 요소(Fragment가 추가될 ViewGroup)를 선언해두어야 한다.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <FrameLayout android:id="@+id/fragment_container" android:layout_weight="1"
            android:layout_width="0px" android:layout_height="match_parent"
            android:background="?android:attr/detailsElementBackground" />

</LinearLayout>
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()

val fragment = ExampleFragment() //Fragment 클래스 파일
fragmentTransaction.add(R.id.fragment_container, fragment)
fragmentTransaction.commit()

 

2. Fragment에 적용할 레이아웃 파일(.xml) 생성

1.1에서 Fragment를 두 개 만들어주었으니 레이아웃 파일을 두 개 만들어준다.

 

3. Fragment 클래스 파일 생성(Fragment를 상속받는 클래스 파일이다), 4. Fragment 레이아웃 파일과 클래스 파일을 View Binding으로 연결(혹은 Fragment 클래스 파일에서 inflate에 지정하여 연결)

아래 코드는 두 개의 Fragment 파일 중 하나의 코드이다.

View Binding으로 2에서 만든 레이아웃 파일과 연결시켜주었다.

class ArticleListFragment : Fragment(){

        lateinit var binding : FragmentArticleListBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        binding = FragmentArticleListBinding.inflate(inflater, container, false)
        return binding.root

    }

}

 

5. 호스팅 Activity 클래스에서 Fragment 클래스를 인스턴스화시킨다(1-2만 해당)

호스팅 Activity 레이아웃에서 Fragment를 명시해주지 않은 경우에 이 단계를 시행해야 한다.

이 경우에는 Activity 실행 도중에 추가되는 경우이므로, 처음에는 빈 화면이었다가 사용자 이벤트에 따라서 Fragment를 추가해주는 식으로 디자인할 수 있다.

Fragment 생명 주기 포스팅에서도 다룰 내용이지만, Fragment 생명 주기 또한 onCreate() 메소드가 구현돼있어야 한다.

또한 이 onCreate() 메소드가 호스팅 Activity에 구현이 되어있다면, onCreate()에서부터 시작을 해야 하므로 Fragment 클래스를 인스턴스화할 때는 onCreate() 메소드에서 시행이 되어야한다.

val fragment = ExampleFragment() //Fragment 클래스 파일

 

6. FragmentTransaction을 사용하여 Fragment를 제어한다

val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()

val fragment = ExampleFragment() //Fragment 클래스 파일
fragmentTransaction.add(R.id.fragment_container, fragment)
fragmentTransaction.commit()

 

재사용성이 높아서 유용하게 활용할 수 있을 것 같다.

또한, ViewPager(이 또한 추후에 포스팅할 예정입니다)라는 위젯과 함께 쓰일 수 있어서 많은 장점을 갖고 있다.

Fragment도 생명 주기를 갖고 있고 이 생명 주기가 Activity에 영향을 받는다.

Activity로 인해 갑자기 Fragment가 종료되는 일이 있을 수도 있으므로 생명 주기에 대한 내용이 중요할 수 있을 것 같다.

따라서 차후의 포스팅에서는 Fragment 생명 주기에 대한 내용을 다뤄볼 것이다.

 

참조

'Android > etc' 카테고리의 다른 글

[Android] Jetpack  (0) 2022.06.21
[Android] SharedPreferences  (0) 2022.06.15
[Android] Glide 라이브러리의 사용  (0) 2022.06.11
[Android] Handler 개념  (0) 2022.06.07
Retrofit 2  (0) 2021.12.28
Comments