개발모음집

프래그먼트 정리 본문

Android

프래그먼트 정리

void 2017. 5. 17. 19:29

* 개인적으로 공부하는 자료

구글 개발자 센터 정리


개념


Fragment는 동작 또는 Activity 내에서 사용자 인터페이스의 일부를 나타냅니다. 여러 개의 프래그먼트를 하나의 액티비티에 조합하여 창이 여러 개인 UI를 구축할 수 있으며, 하나의 프래그먼트를 여러 액티비티에서 재사용할 수 있습니다. 프래그먼트는 자체 수명 주기를 가지고, 자체 입력 이벤트를 받으며, 액티비티 실행 중에 추가 및 제거가 가능한 액티비티의 모듈식 섹션이라고 생각하면 됩니다(다른 액티비티에 재사용할 수 있는 "하위 액티비티"와 같은 개념).

프래그먼트는 항상 액티비티 내에 포함되어 있어야 하며 해당 프래그먼트의 수명 주기는 호스트 액티비티의 수명 주기에 직접적으로 영향을 받습니다. 예를 들어 액티비티가 일시정지되는 경우, 그 안의 모든 프래그먼트도 일시정지되며 액티비티가 소멸되면 모든 프래그먼트도 마찬가지로 소멸됩니다. 그러나 액티비티가 실행 중인 동안에는(재개됨 수명 주기 상태에 있을 때를 말합니다) 각 프래그먼트를 추가 또는 제거하는 등 개별적으로 조작할 수 있습니다.


디자인 철학

프래그먼트를 디자인할 때에는 각 프래그먼트를 모듈식이며 재사용 가능한 액티비티 구성 요소로 만들어야 합니다. 다시 말해, 각 프래그먼트가 나름의 레이아웃을 따로 정의하고 자기만의 수명 주기 콜백으로 자기 나름의 동작을 정의하기 때문에 한 프래그먼트를 여러 액티비티에 포함시킬 수 있습니다. 그러므로 재사용을 염두에 두고 디자인하며 한 프래그먼트를 또 다른 프래그먼트로부터 직접 조작하는 것은 삼가야 합니다. 이것은 특히 모듈식 프래그먼트를 사용하면 프래그먼트 조합을 여러 가지 화면 크기에 맞춰 변경할 수 있도록 해주기 때문에 중요한 요점입니다.


프래그먼트는 화면에 출력 가능한 일반 뷰가 아니며 동시에 액티비티와 같은 컴포넌트도 아니다.



액티비티 생명주기


프래그먼트 생명주기

최소한 구현해야하는 메서드 3개

onCreate : 프래그먼트를 생성할 때 호출

onCreateView : 프래그먼트가 처음 ui를 그릴 때 호출, view를 반환해야한다.

onpause : 사용자가 떠난다는 첫 번째 신호


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

ui 有

1. 프래그먼트를 액티비티의 레이아웃 파일 안에서 선언 => xml 방식

2.프로그래밍 방식으로 프래그먼트를 기존의 viewGroup에 추가 => 자바 방식


ui 無

ui를 추가로 제시하지 않고 액티비티에 대한 백그라운드 동작을 제공하기 위해 프래그먼트를 사용할 수 있다.



프래그먼트 관리

액티비티 내의 프래그먼트를 관리하려면 FragmentManager를 사용해야 한다. 이것을 가져오려면 액티비티에서 getFragmentManager()를 호출해야 한다.

FragmentManager 기능

1. 액티비티 내에 존재하는 프래그먼트를 findFragmentById()로 가져오기  (ui 有)

또는 findFragmentByTag()로 가져오기 (ui 無)


2. popBackStack()을 사용하여 프래그먼트를 백 스택에서 꺼낸다. (사용자가 Back 명령을 시뮬레이션)


3. 백 스택에 변경 내용이 있는지 알아보기 위해 addOnBackStackChangedListener()로 리스너를 등록합니다.


프래그먼트 트랜잭션 수행


액티비티에서 프래그먼트를 사용하는 경우 특히 유용한 점은 사용자 상호작용에 응답하여 추가, 제거, 교체 및 다른 작업을 수행할 수 있다는 것이다.

FragmentTransaction의 인스턴스를 FragmentManager로부터 가져오는 방법은 다음과 같습니다.


FragmentManager fragmentManager = getFragmentManager();

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

각 트랜잭션은 동시에 수행하고자 하는 변경 집합이다. 주어진 트랜잭션에 대해 수행하고자 하는 모든 변경 사항을 설정하려면 add(), remove(), 및 replace()와 같은 메서드를 사용하면 된다. 그런 다음, 트랜잭션을 액티비티에 적용하려면 반드시 commit()을 호출해야 한다.

하지만 commit()을 호출하기 전에 먼저 호출해야 할 것이 있다. 바로 addToBackStack()이다. 이렇게 해야 트랜잭션을 프래그먼트 트랜잭션의 백 스택에 추가할 수 있다. 이 백 스택을 액티비티가 관리하며, 이를 통해 사용자가 이전 프래그먼트 상태로 되돌아갈 수 있다. 이때 Back 버튼을 누르면 된다.

예를 들어 다음은 한 프래그먼트를 다른 것으로 교체하고 이전 상태를 백 스택에 보존하는 방법을 보여줍니다.


// Create new fragment and transaction

Fragment newFragment = new ExampleFragment();

FragmentTransaction transaction = getFragmentManager().beginTransaction();


// Replace whatever is in the fragment_container view with this fragment,

// and add the transaction to the back stack

transaction.replace(R.id.fragment_container, newFragment);

transaction.addToBackStack(null);


// Commit the transaction

transaction.commit();

이 예시에서는 newFragment가 현재 레이아웃 컨테이너에서 식별된 프래그먼트(있는 경우)를 R.id.fragment_container ID로 교체한다.

addToBackStack()를 호출함으로써 교체 트랜잭션이 백 스택에 저장되므로, 

사용자가 Back 버튼을 눌러 트랜잭션을 되돌리고 이전 프래그먼트를 다시 가져올 수 있다.


트랜잭션에 여러 개의 변경을 추가하고(예: 또 다른 add() 또는 remove()), addToBackStack()을 호출하면, commit()을 호출하기 전에 적용된 모든 변경 내용이 백 스택에 하나의 트랜잭션으로 추가되며, Back 버튼을 누르면 모두 한꺼번에 되돌려진다.

FragmentTransaction에 변경 내용을 추가하는 순서는 중요하지 않다. 다만 다음과 같은 예외가 있다.

commit()을 마지막으로 호출해야 한다.

같은 컨테이너에 여러 개의 프래그먼트를 추가하는 경우, 이를 추가하는 순서가 이들이 뷰 계층에 나타나는 순서를 결정 짓는다.

프래그먼트를 제거하는 트랜잭션을 수행하면서 addToBackStack()을 호출하지 않는 경우, 해당 프래그먼트는 트랜잭션이 적용되면 소멸되고 사용자가 이를 되짚어 탐색할 수 없게 됩니다. 반면에 프래그먼트를 제거하면서 addToBackStack()을 호출하면, 해당 프래그먼트는 중단되고 사용자가 뒤로 탐색하면 재개된다.

=> 즉 addToBackStack()있으면 그 전 프래그먼트가 사라지지않는다!

팁: 각 프래그먼트 트랜잭션에 대해 전환 애니메이션을 적용하려면 커밋하기 전에 setTransition()을 호출하면 ㄷ다.


commit()을 호출해도 그 즉시 트랜잭션을 수행하지는 않는다. 그보다는, 액티비티의 UI 스레드("주요" 스레드)를 스레드가 할 수 있는 한 빨리 이 트랜잭션을 수행하도록 일정을 예약하는 것에 가깝다. 하지만 필요한 경우 UI 스레드로부터 executePendingTransactions()를 호출하면 commit()이 제출한 트랜잭션을 즉시 실행할 수 있습니다. 트랜잭션이 다른 스레드의 작업에 대한 종속성이 아니라면 굳이 이렇게 해야만 하는 것은 아니다.

주의: 트랜잭션을 커밋할 때 commit()을 사용해도 되는 것은 (사용자가 액티비티를 떠날 때) 액티비티가 그 상태를 저장하기 전뿐이다. 그 시점 이후에 적용하려고 하면 예외가 발생이다. 이것은 액티비티를 복원해야 하는 경우 적용 이후의 상태가 손실될 수 있기 때문이다. 커밋이 손실되어도 괜찮은 상황이라면, commitAllowingStateLoss()를 사용해라.


액티비티와의 통신


Fragment는 Activity로부터 독립적인 객체로 구현되었고 여러 개의 액티비티 안에서 사용할 수 있는 것이 사실이지만, 프래그먼트의 주어진 인스턴스는  그것을 포함하고 있는 액티비티에 직접적으로 연결되어 있다.

구체적으로 말하면, 이 프래그먼트는 getActivity()를 사용하여 Activity 인스턴스에 액세스하여 액티비티 레이아웃에서 뷰를 찾는 것과 같은 작업을 손쉽게 수행할 수 있다.

View listView = getActivity().findViewById(R.id.list);

이와 마찬가지로, 액티비티도 프래그먼트 안의 메서드를 호출할 수 있다. 그러려면 FragmentManager로부터의 Fragment에 대한 참조를 가져와야 하며, 이때 findFragmentById() 또는 findFragmentByTag()를 사용합니다. 

예:

ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment)


액티비티로의 이벤트 콜백 생성

어떤 경우에는 프래그먼트로 하여금 액티비티와 이벤트를 공유하게 해야 할 수 있다. 이렇게 하기 위한 한 가지 좋은 방법은 프래그먼트 내부의 콜백 인터페이스를 정의한 다음 해당 호스트 액티비티가 이를 구현하도록 하는 것이다. 액티비티가 인터페이스를 통해 콜백을 수신하면, 필요에 따라 그 정보를 레이아웃 내의 다른 프래그먼트와 공유할 수 있다. => a 프래그먼트와 b 프래그먼트가 이벤트를 연결하려면 액티비티를 통해서 해야한다

예를 들어 어떤 뉴스 애플리케이션에서 액티비티 하나에 프래그먼트가 두 개 있다. 하나는 기사 목록을 표시(프래그먼트 A)하고 다른 하나는 기사 하나를 표시(프래그먼트 B)하는 경우 목록 항목이 선택되면 프래그먼트 A가 액티비티에 알려야 프래그먼트 B에 해당 기사를 표시하라고 알릴 수 있습니다. 이 경우, OnArticleSelectedListener 인터페이스는 프래그먼트 A 내부에 선언됩니다.

public static class FragmentA extends ListFragment {

    ...

    // Container Activity must implement this interface

    public interface OnArticleSelectedListener {

        public void onArticleSelected(Uri articleUri);

    }

    ...

}

액티비티가 인터페이스를 구현하지 않은 경우, 프래그먼트가 ClassCastException을 발생시킵니다. 성공 시, mListener 멤버가 액티비티의 OnArticleSelectedListener 구현에 대한 참조를 보유하므로, 프래그먼트 A가 액티비티와 이벤트를 공유할 수 있다. 이때 OnArticleSelectedListener 인터페이스가 정의한 메서드를 호출하는 방법을 사용한다. 예를 들어 프래그먼트 A가 ListFragment의 확장인 경우, 사용자가 목록 항목을 클릭할 때마다 시스템이 프래그먼트 안의 onListItemClick()을 호출하고, 그러면 이것이 onArticleSelected()를 호출하여 해당 이벤트를 액티비티와 공유하는 것이다.

=> 액티비티에 인터페이스가 없으면 프래그먼트가 예외처리함.

OnArticleSelectedListener가 정의한 메서드를 호출함으로서 

OnArticleSelectedListener로 액티비티와 프래그먼트가 이벤트를 공유할 수 있다.



public static class FragmentA extends ListFragment {

    OnArticleSelectedListener mListener;

    ...

    @Override

    public void onListItemClick(ListView l, View v, int position, long id) {

        // Append the clicked item's row ID with the content provider Uri

        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);

        // Send the event and Uri to the host activity

        mListener.onArticleSelected(noteUri);

    }

    ...

}

onListItemClick()에 전달된 id 매개변수는 클릭한 항목의 행 ID이며, 액티비티(또는 다른 프래그먼트)가 이것을 사용해 애플리케이션의 ContentProvider에서 기사를 가져옵니다.

콘텐츠 제공자 사용법에 대한 자세한 정보는 콘텐츠 제공자 문서에서 이용하실 수 있습니다.


앱 바에 항목 추가


프래그먼트는 액티비티의 옵션 메뉴에(결과적으로 앱 바에도) 메뉴 항목을 추가할 수 있습니다. 이때 onCreateOptionsMenu()를 구현하는 방법을 쓴다. 이 메서드가 호출을 수신하도록 하려면, setHasOptionsMenu() 중에 onCreate()를 호출하여 프래그먼트가 옵션 메뉴에 항목을 추가하고자 한다는 것을 나타내야 한다(그렇지 않으면 해당 프래그먼트가 onCreateOptionsMenu()로의 호출을 받지 못하게 됩니다).

그런 다음 프래그먼트로부터 옵션 메뉴에 추가하는 모든 항목은 기존의 메뉴 항목에 추가된다. 메뉴 항목을 선택하면 해당 프래그먼트는 onOptionsItemSelected() 콜백도 수신하게 된다.

또한 프래그먼트 레이아웃에 뷰를 등록하여 컨텍스트 메뉴를 제공하도록 할 수도 있습니다. 이때 registerForContextMenu()를 호출하면 됩니다. 사용자가 컨텍스트 메뉴를 열면, 해당 프래그먼트는 {@linkandroid.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) onCreateContextMenu()} 호출을 수신합니다. 사용자가 항목을 선택하면, 해당 프래그먼트는 onContextItemSelected() 호출을 수신합니다.


참고: 프래그먼트는 추가한 각 메뉴 항목이 선택될 때 콜백을 받게 되지만, 사용자가 메뉴 항목을 선택할 때 그에 상응하는 콜백을 가장 처음 받는 것은 액티비티이다. 액티비티가 구현한 항목 선택 시 콜백이 선택된 항목을 다루지 않는 경우, 해당 이벤트는 프래그먼트의 콜백으로 전달됩니다. 이는 옵션 메뉴와 컨텍스트 메뉴에 모두 해당됩니다.

메뉴에 대한 자세한 내용은, 메뉴 개발자 가이드와 앱 바 교육 과정을 참조하세요.


프래그먼트 수명 주기 처리


프래그먼트는 세 가지 상태로 존재할 수 있다.

재개됨(Resumed)

프래그먼트가 실행 중인 액티비티에 표시됩니다.

일시정지됨(Paused)

또 다른 액티비티가 포그라운드에 있고 포커스를 갖고 있지만, 이 프래그먼트가 있는 액티비티도 여전히 표시됩니다(포그라운드의 액티비티가 부분적으로 투명하거나 전체 화면을 뒤덮지 않습니다).

정지됨(Stopped)

프래그먼트가 표시되지 않습니다. 호스트 액티비티가 정지되었거나 프래그먼트가 액티비티에서 제거되었지만 백 스택에 추가되었습니다. 정지된 프래그먼트도 여전히 표시는 됩니다(모든 상태 및 멤버 정보를 시스템이 보존합니다). 하지만, 사용자에게는 더 이상 표시되지 않으며 액티비티를 종료하면 이것도 종료됩니다.

이번에도 액티비티와 마찬가지로, 프래그먼트의 상태를 보존하려면 Bundle을 사용한다. 이는 혹시나 액티비티의 프로세스가 종료되고 액티비티를 다시 만들 때 해당 프래그먼트의 상태를 복구해야 할 필요가 있을 때를 대비하는 것이다. 프래그먼트의 onSaveInstanceState() 콜백 중에 상태를 저장할 수 있고, onCreate(), onCreateView() 또는 onActivityCreated() 중에 상태를 복구할 수 있다. 


액티비티와 프래그먼트의 수명 주기에서 가장 중대한 차이점은 해당되는 백 스택저장되는 방법입니다. 액티비티는 기본적으로 중단되었을 때 시스템이 관리하는 액티비티 백 스택 안에 배치됩니다. (따라서 사용자가 Back 버튼을 사용하여 다시 이 액티비티로 돌아갈 수 있습니다. 이 내용은 작업 및 백 스택에서 설명하였습니다.) 하지만, 프래그먼트가 호스트 액티비티가 관리하는 백 스택 안에 배치되는 경우는 트랜잭션 동안 프래그먼트를 제거하는 addToBackStack()을 호출하여 해당 인스턴스를 저장하라고 명시적으로 요청하는 경우뿐입니다.

이것만 제외하면, 프래그먼트 수명 주기를 관리하는 것은 액티비티의 수명 주기를 관리하는 것과 아주 비슷합니다. 따라서, 액티비티 수명 주기 관리에 쓰이는 사례가 프래그먼트에도 똑같이 적용됩니다. 하지만 또 한 가지 이해해두어야 하는 것이 있습니다. 즉, 액티비티의 수명이 프래그먼트의 수명에 어떤 영향을 미치는지를 알아두어야 합니다.

주의: Fragment 내에서 Context 객체가 필요한 경우, getActivity()를 호출하면 됩니다. 그러나 getActivity()를 호출하는 것은 프래그먼트가 액티비티에 첨부되어 있는 경우뿐이니 유의하세요. 프래그먼트가 아직 첨부되지 않았거나 수명 주기가 끝날 무렵 분리된 경우, getActivity()가 null을 반환합니다.


액티비티 수명 주기와의 조화


프래그먼트가 있는 액티비티의 수명 주기는 해당 프래그먼트의 수명 주기에 직접적인 영향을 미칩니다. 따라서 액티비티에 대한 각 수명 주기 콜백이 각 프래그먼트에 대한 비슷한 콜백을 유발합니다. 예를 들어 액티비티가 onPause()를 받으면, 해당 액티비티 내의 각 프래그먼트가 onPause()를 받습니다.

하지만, 프래그먼트에는 프래그먼트의 UI를 구축하고 소멸시키는 것과 같은 작업을 하기 위해 액티비티와의 고유한 상호작용을 처리하는 몇 가지 수명 주기 콜백이 더 있습니다. 이러한 추가 콜백 메서드에는 다음과 같은 것들이 있습니다.


onAttach()

프래그먼트가 액티비티와 연관되어 있었던 경우 호출됩니다(여기에서 Activity가 전달됩니다).

onCreateView()

프래그먼트와 연관된 뷰 계층을 생성하기 위해 호출됩니다.

onActivityCreated()

액티비티의 onCreate() 메서드가 반환되면 호출됩니다.

onDestroyView()

프래그먼트와 연관된 뷰 계층이 제거되는 중일 때 호출됩니다.

onDetach()

프래그먼트가 액티비티와 연결이 끊어지는 중일 때 호출됩니다.


호스트 액티비티의 영향을 받는 동안 프래그먼트 수명 주기의 흐름이 그림 3에 나타나 있습니다. 이 그림에서는 프래그먼트가 어떤 콜백 메서드를 수신할지 여부는 액티비티의 각 연속된 상태에 따라 결정된다는 것을 보여줍니다. 예를 들어 액티비티가 자신의 onCreate() 콜백을 받은 경우, 해당 액티비티 안에 있는 프래그먼트는 onActivityCreated() 콜백을 받을 뿐입니다.

액티비티가 재개된 상태에 도달하면 자유자재로 프래그먼트를 액티비티에 추가하거나 액티비티에서 제거해도 됩니다. 따라서, 액티비티가 재개된 상태에 있는 동안에만 프래그먼트의 수명 주기를 독립적으로 변경할 수 있습니다.

그러나 액티비티가 재개된 상태를 떠나면 액티비티는 다시 프래그먼트를 그 수명 주기 안으로 넣습니다.


객체 지향으로 배우는 안드로이드 프로그래밍


프래그먼트 특징

1. 프래그먼트 요소는 XML 레이아웃 내 뷰 요소와 같이 선언하고 사용할 수 있다.

2. 프래그먼트 요소는 android:name 속성 또는 class속성을 사용하여 안드로이드에 대응되는 프래그먼트 클래스를 알려 주어야 한다.

클래스명은 패키지 이름을 포함하여 정식 클래스명(.Full Qualified Class)으로 명시해 주어야 한다.

3.프래그먼트 클래스는 인스턴스화되고 액티비티와 연결하는 과정에 있어 프래그먼트 자체 생명주기가 작동한다.

주의할 점

프래그먼트를 레이아웃 내 다른 프레그먼트와 식별하는 법


1. android:id 속성으로 고유 아이디 부여 (ui 있을 때)

2. android:tag 속성을 고유 태그 부여 (ui 없을 때)

프래그먼트 요소에 식별가능한 아이디나 태그를 부여하지 않는 다면, 프래그먼트 요소를 감싸는 레이아웃에 아이디를 부여한다. 이 경우 레이아웃 내 반드시 하나의 프래그먼트 요소만 존재해야한다.


public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

프래그먼트는 뷰 요소가 아니기 때문에 필요한 뷰를 화면에 출력시켜 주기 위해 onCreateView() 콜백메서드를 사용한다.

onCreateView() 콜백 메소드는 뷰나 뷰그룹을 xml 프래그먼트 요소에 출력할 수 있도록 인플레이터와 상단의 뷰그룹 그리고 번들 객체를 제공한다.

그리고 반환하는 객체는 화면에 출력할 View 객체가 된다.

onCreateView()는 다음과 같이 세 종류의 매개 변수를 제공

첫 번째 매개 변수는 뷰나 xml 레이아웃을 인플레이션할 수 있는 LayoutInflater 객체를 제공한다.

두 번째 매개 변수는 액티비티에서 setContentView(R.layout.main)  메소드처럼 xml 레이아웃을 인스턴스화하면서 생선된 레이아웃 객체를 ViewGroup 객체로 제공한다.

*주의할 점

매개 변수로 받은 ViewGroup객체라 하더라도 뷰그룹 클래스에서 제공하는 addView() 메소드를 사용하여 뷰를 추가하려면 예외가 발생한다.


세 번째 매개 변수는 프래그먼트 클래스에서 자체 생명주기에 따라 onSaveInstanceState() 콜백 메소드로 저장한 번들 객체이다. 만약 설정 변경이 발생되어 프래그먼트가 재호출이 되었을 때 사용할 수 있도록 제공한다.


생명주기

onAttach : 프래그먼트 호출, 콜백 메소드의 매개변수 프래그먼트를 호출하는 액티비티 객체다

onCreate: 액티비티 클래스 내 onCreate() 메소드처럼 기존에 저장한 데이터를 번들 객체로 제공 액티비티 - 프래그먼트 연결이 이루어지지 않은 상태, 주로 프로그래먼트 실행에 필요한 환경을 설정하기 위해 사용


onCreateView() view들을 인플레이션하는 기능 반환하는 객체는 View() 객체

onActivityCreated() 프래그먼트 - 액티비티 연결되는 시점에 호출

onDestroy() 메서드와 연결되는 콜백 메소드

onDestroyView() : 프래그먼트에서 뷰를 제거하기 전에 호출되는 콜백 메소드

onDestroy() 프래그먼트객체를 제거하기 전에 호출되는 메소드

onDetach() 액티비티 - 프래그먼트 연결관계를 삭제할 때 호출되는 메소드

 


==> 정리

1.프래그먼트 역시 생성되고 삭제되는 과정을 겪는다.

2. onAttach 자신(프래그먼트)을 호출한 액티비티를 프로그먼트에 알려준다.

3. 프래그먼트가 소멸되고 생성될 때마다 내부적으로 필요로 하는 데이터를 번들 객체로 저장한다.

4. 프래그먼트 -> 화면내 작은 기능의 액티비티, 뷰 또는 뷰그룹출력 가능


뷰그룹과 프래그먼트간의 연동


뷰그룹과 프래그먼트간의 연동


정적 프래그먼트 : 레이아웃 파일에 선언해서 붙이기

동적 프래그먼트 : 프래그먼트 매니저를 통해서 붙이기



동적 프래그먼트 동작방법

1. 프래그먼트 매니저 객체를 생성한다.

* FragmentManager 클래스는 프래그먼트의 스택관리, 덤프나 로그, 액티비티와 연결된 프래그먼트 찾기 기능을 제공

FragmentManager fragmentManager = getFragmentManager();


2. 프래그먼트-트랜잭션 객체를 생성한다.

* xml 레이아웃 내 뷰그룹과 프래그먼트를 서로 연결

* 사용자가 백키를 눌렀을 때 액티비티처럼 프래그먼의 스택에 저장된 프래그먼트 객체를 호출

*xml 레이아웃에서 프래그먼트를 교체하거나 삭제한다.

FragmentTransaction fragmentTransaction = fragmentTransaction.beginTransaction(); 


3. 프래그먼트 클래스의 인스턴스를 생성한다.

ExampleFragment fragment = new ExampleFragment();


4. 프래그먼트-트랜잭션 객체를 사용하여 뷰그룹에 프래그먼트 객체를 추가한다.

5. commit() 메소드로 작업이 완료되었음을 알린다.




생명주기 로그로 확인


// 처음 생성될 때

E/Activity: onCreate 

E/Fragment: onAttach (onCreate 내 setContentView() 메소드 호출 전)

E/Fragment: onCreate

E/Fragment: onCreateView

E/Activity: onStart

E/Fragment: onActivityCreated

E/Fragment: onStart

E/Activity: onResume

E/Fragment: onResume



// 다른 액티비티띄었을 때

E/Activity: onPause

E/Fragment: onStop


// 다른 액티비티에서 백버튼 눌렀을 때

E/Activity: onRestart

E/Activity: onStart

E/Fragment: onStart

E/Activity: onResume

E/Fragment: onResume


홈화면으로 갔을 때

E/Activity: onPause

E/Fragment: onStop


홈화면에서 액티비티를 켰을 때


E/Activity: onRestart

E/Activity: onStart

E/Fragment: onStart

E/Activity: onResume

E/Fragment: onResume


생각해보자


프래그먼트가 왜 생겼을까?

디바이스의 크기가 다양해지고 큰 화면이 나오면서 두 액티비티에서 구현하던걸 

한 액티비티에서 구현하고 싶어서 만들었다.


프래그먼트의 이점은?

액티비티에서 ui없이도 동작이 가능 - 서비스와 비슷한 역할을 할 수 있을 것으로 추측됨

여러 액티비티에서 재사용이 가능


단점 재사용성으로 인하여 고려해야할 점이 늘어나 액티비티만 쓸 때보다 더 복잡해진다.


** 참고 사항

Callback-notitle.svg

콜백: 프로그래밍에서 콜백은 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 말한다.