본문 바로가기
Android/Android 기초

[Android] 프래그먼트(Fragment)

by 태크민 2023. 9. 6.

프래그먼트(Frament)

프래그먼트는 액티비티 내에 생성되는 UI 구성을 여러 개의 모듈 단위로 작성할 수 있도록 해주는 역할을 한다.

 

프래그먼트의 특징

  • 프래그먼트는 독립적일 수 없다.
    • 액티비티에 종속적이다. 따라서 액티비티가 중단되면 그 액티비티에 속해있던 모든 프래그먼트도 함께 중단된다.
  • 액티비티에 비해 가볍다.
    • 액티비티는 안드로이드 시스템에서 관리하지만, 프래그먼트는 안드로이드 시스템이 직접 관리하지 않고 프래그먼트 매니저가 관리하기 때문에 메모리 리소스가 상대적으로 덜 소모되어 액티비티보다 가볍다.
  • 다른 액티비티에서도 사용할 수 있어 재사용성이 뛰어나다.
    • 액티비티의 화면 구성을 위한 레이아웃의 복잡도를 줄일 수 있다.
  • 액티비티와 같이 레이아웃, 생명주기를 가진다.
  • 액티비티 내에서 런타임 중에 추가, 제거가 가능하다.

프래그먼트의(Fragment) 생명주기

onAttach()

프래그먼트가 액티비티에 연결될 때 호출된다.

파라미터로 액티비티의 context가 넘어온다.

onCreate()

프래그먼트를 생성할 때 호출한다.

하지만, 이 시점에는 아직 Fragment View가 생성되지 않았기 때문에 Fragment의 View와 관련된 작업을 두기에는 적절하지 않다.

onCreateView()

프래그먼트의 Layout을 inflate하여 View 객체를 얻을 수 있다.

View 객체를 얻을 수 있기 때문에 프래그먼트에 속한 View나 ViewGroup에 대한 UI 바인딩을 할 수 있다.

onActivityCreated()

액티비티에서 프래그먼트를 모두 생성하고 난 다음에 호출된다. 즉, 액티비티에서 onCreate() 다음에 호출된다. 액티비티와 프래그먼트가 연결되는 시점이다.

onStart()

프래그먼트가 사용자에게 보여지기 전에 호출되는 함수

onResume()

프래그먼트가 화면에 보여지게 되면서 사용자와 상호작용을 하기 직전에 호출된다. 화면에 포커스를 잡은 상태이며 사용자와의 상호작용이 가능하다.

onPause()

다른 프래그먼트가 화면을 가리게 되어 기존 프래그먼트의 화면이 사라지게 되는 시점에서 첫번째로 호출, 기존 레이아웃은 백스택으로 돌아감

onStop()

화면을 완전히 가리게되면 onStop()을 호출한다. onStop()에서 유저가 해당 프래그먼트를 호출하면 다시 복원될 수 있는 상태이다.

onDestroyView()

프래그먼트와 연결된 View Layer가 제거될 때 호출된다. (View들의 리소스를 해제되는 구간)

onDestroy()

프래그먼트가 완전히 소멸될 때 호출

onDetach()

프래그먼트가 액티비티와 연결이 끊기기 직전에 호출

 

 


 

프래그먼트 매니저(Fragment Manager)

액티비티와 프래그먼트의 중간에서 서로를 이어주는 역할을 하는 것이 프래그먼트 매니저이다.

액티비티 매니저, 프래그먼트 매니저

프래그먼트 매니저의 역할

1. 프래그먼트 트랜잭션 수행

프래그먼트 매니저는 액티비티가 사용자의 입력 이벤트에 따라 프래그먼트를 추가 및 삭제 그리고 교체 등의 작업을 수행할 수 있게 해준다. 

뿐만 아니라, 행해진 트랜잭션의 상태를 프래그먼트 백스택(BackStack)을 통해 저장할 수 있다.

트랜잭션?
어떤 대상에 대해 추가, 제거, 변경 등의 작업이 발생하는 것을 묶어서 얘기하는 것이다.

2. 특정 프래그먼트 자원 접근 가능

프래그먼트 매니저를 통해 액티비티에서 프래그먼트에 대한 자원을 직접적으로 접근 할 수 있다.

FragmentManager에 속한 findFragmentById(), findFragmentByTag() 등으로 원하는 프래그먼트의 참조를 가져와 해당 프래그먼트의 각종 함수, 변수에 접근이 가능하다.

FirstFragment fragment = (FirstFragment) getSupportFragmentManager().findFragmentById(R.id.first_fragment);

3. 백스택 관리

프래그먼트 매니저는 addToBackStack() 메소드를 호출하여 프래그먼트 트랜잭션을 백스택에 push한다.

또한, popBackStack() 함수를 호출하면 백스택에 저장되어 있는 프래그먼트 트랜잭션 중 스택의 가장 최상단에 존재하는 트랜잭션을 제거(pop)할 수 있다. (사용자가 'Back' 버튼을 눌렀을 때는 내부적으로 자동 호출)

안드로이드의 백스택(BackStack)

FragmentTransaction transaction = getActivity()
	.getSupportFragmentManager()
	.beginTransaction()
	.add(R.id.main_container, movieInfoFragment);

// 해당 transaction 을 Back Stack 에 저장
transaction.addToBackStack(null);
// transaction 실행
transaction.commit();

 


 

액티비티에 프래그먼트 추가하기

액티비티에 프래그먼트를 추가하는 방법은 두가지가 있다.

  1. 액티비티 xml 리소스에 Fragemnt를 직접  추가하는 방법
  2. FragmentManager 클래스를 사용하여 프래그먼트를 추가하는 방법

액티비티 xml 리소스에 Fragemnt를 직접  추가하는 방법

이 방법의 경우 처음 화면에 출력될 프래그먼트를 지정하거나 화면에서의 동적 변화가 없는 경우에 주로 사용한다.

아래 코드에서 Fragment의 속성 중 "android:name"에 화면에 출력할 Frament 클래스를 지정한다.

<activity_main.xml>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ....
    <fragment
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/fragmentA"
        android:name="com.recipes4dev.examples.fragmentexample1.FragmentA"
        android:layout_weight="1"
        tools:layout="@layout/activity_main" 
		/>
</LinearLayout>

 

FragmentManager 클래스를 사용하여 프래그먼트를 추가하는 방법

이 방법의 경우 앱 실행 중 프래그먼트를 동적으로 추가하거나 변경할 때 사용한다.

[activity_main.xml]

<activity_main.xml>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ....
    <fragment
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/fragmentA"
        android:name="com.recipes4dev.examples.fragmentexample1.FragmentA"
        android:layout_weight="1"
        tools:layout="@layout/activity_main" 
		/>
</LinearLayout>

[MainActivity]

  @Override
    protected void onCreate(Bundle savedInstanceState) {
// ....
	FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fm.beginTransaction();
        fragmentTransaction.add(R.id.fragmentBorC, new FragmentB());
        fragmentTransaction.commit();// 코드 계속 ...
    }