Fragment
프래그먼트에대해 알아보기전 알면 도움이 되는 것들 인스턴스란 (헷갈려? 이거봐) 싱글톤이란 (뭐지 정확히? 이거봐)
Fragment 란
사전적으로는 파편이라는 뜻을 가진 단어이다.
즉, 활동에서의 파편들을 의미한다 대충 이해하고 들어가보자.안드로이드 개발자에서 공식 정의는 아래와 같다.
Fragment는 앱 UI의 재사용 가능한 부분을 나타냅니다. 프래그먼트는 자체 레이아웃을 정의 및 관리하고 자체 수명 주기를 보유하며 자체 입력 이벤트를 처리할 수 있습니다. 프래그먼트는 독립적으로 존재할 수 없고 활동이나 다른 프래그먼트에서 호스팅 되어야 합니다. 프래그먼트의 뷰 계층 구조는 호스트 뷰 계층 구조의 일부가 되거나 여기에 연결됩니다. [공식문서보기]
프래그먼트를 사용하는 앱은 올바른 방법으로 설계해야 한다.
많은 개발자가 프래그먼트를 배우자마자 앱의 모든 컴포넌트에 프래그먼트를 사용하려고 하는데,
이 방식은 프래그먼트를 잘못 사용하는 것이다.
- 안드로이드 프로그래밍 저자 -
프래그먼트는 어떨때 사용해야 좋을까?
프래그먼트를 고려하는 개발자라면 이와 같은 근본적인 질문과 궁금증이 있을 것이다.
프래그먼트는 많은 요구사항을 갖는 큰 애플리케이션에 유용하다.
반면에 간단하고 단일 화면을 갖는 애플리케이션에는 프래그먼트가 필요하지 않다.
프래그먼트의 역사
Fragment class 는 허니콤(Honeycomb) 버전에 추가되었다. 허니콤은 3.0~3.2버전으로, API level 11~13에 해당된다.
(허니콤은 2011년 2월에 출시하여, 2014년 2월까지 업데이트되다가, 현재는 지원이 종료 되었다.)
프래그먼트의 기능과 사용법
Fragment는 주요 컴포넌트를 재사용하게끔 캡슐화한다. 컴포넌트들은 여러 기능을 가진 뷰라 생각하면,
이러한 컴포넌트들을 가진 여러 프래그먼트를 한 화면에 넣어버리면, 트랜잭션 때문에 코드가 복잡, 지저분 해진다.
따라서, 작은 컴포넌트들을 재사용할 때는 프래그먼트 대신 커스텀 뷰로 추출하는 것이 좋은 방법이다.
(일반적으론, 한 화면에 최대 두개, 세개 정도를 사용하자.)
Fragment는 FragmentManager 를 활용하여 액티비티에 뷰를 올리도록 설계되어있다.
FragmentManager는 프래그먼트의 뷰를 액티비티의 뷰 계층에 추가하고 프래그먼트의 생명주기를 주도하는 책임을 갖는다.
Fragment을 사용하기 위해 Activity에서 사용되는 함수
대표적으로 FragmentTransaction FragmentManager 을 활용한다.
onCreate()...
{
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (currentFragment == null) {
val fragment = CrimeFragment()
supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, fragment) //fragment가 들어갈 곳에 crimefrag를 추가해준다는 의미이다. remove,attach,detach,replace등이 있다.
.commit()
}
먼저 supportFragmentManager를 활용하여, Fragment를 받아줄 액티비티에 선언해준다.
(supportFragmentManager 는 v4라이브러리 출신이지만, jetpack, androidx에 포함되어 발전되어 왔다.)
여기서 FragmentManger는 Fragment 트랜젝션의 백 스택을 유지 관리한다.
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
매니저를 일단 호출하고, findFragmentById를 통해 프래그먼트를 올릴 화면을 매니저에게 알려주는 것이다.
이 후, 해당 Fragment를 선언해준뒤, 트랜젝션을 시작하여, 프래그먼트를 add, remove, attach, detach, replace 등의 명령어를 추가하여 만들고 commit해준다. Fragment 트랜잭션을 사용하면 여러개의 오퍼레이션을 묶어서 수행할 수 있다.
예를들어, 다수의 Fragment를 동시에 서로 다른 컨테이너에 추가하는 경우, Fragment로 런타임 시에 화면을 구성 또는 변경하는 방법의 핵심이 바로 Fragment 트랜잭션이다. 트랜잭션이 백 스택에서 제거되면, 그만큼 manager의 일도 많아진다.
그러므로 다수의 Fragment 오퍼레이션들을 하나의 트랜잭션으로 묶으면 UI상태를 더욱 잘 제어할 수 있다.
FragmentManager.beginTransaction()함수는 FragmentTransaction의 인스턴스를 생성해 반환한다.
Fragment 트랜잭션은 플루언트 인터페이스(fluent interface)를 사용한다.
(인터페이스(fluent interface)는 코드를 이해하기 쉽게 해주는 객체지향 기법이다. 일반적으로 함수의 연쇄 호출 형태로 구현된다.)
supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit()
이 부분이 플루언트 인터페이스의 예라고 생각하면 된다.
add() 함수에서, 매개변수는 두가지이다. 컨테이녀 뷰의 ID와 새로 생성된 프래그먼트 인스턴스이다.
FragmentManager 와 Fragment LifeCycle 생명주기 알아보기
Fragment 의 생명주기는 Activity와 유사하다.
네 가지의 상태를 가지는 것은 동일하다.
그리고 상태가 전환될 때 필요한 일을 처리하기 위해 오버라이드할 수 있는 함수들이 대응된다.
왜냐하면, 액티비티를 대신하여 작동하는 것이 프래그먼트이다. 따라서 액티비티의 작업을 처리하기 위해 액티비티와 일치하는 생명주기 함수가 필요한 것이다.
그래도 차이가 없는 것일까?
아니다, 있다. 프래그먼트 생명주기 함수는 안드로이드 운영체계가 아닌 호스팅 액티비티의 FragmentManager가 호출된다는 점이 큰 차이 이다.
Fragment에서의 함수들
onAttach(Context?) | onCreate(Bundle?) | onCreateView(...) | onViewCreated(...) |
위의 함수들은 FragmentManger에 추가할 때 호출 된다.
onActivityCreated(Bundle?) |
위의 함수는 호스팅 액티비티의 onCreate(Bundle?) 함수가 실행 된 후 호출된다. 앱에서는 MainActivity.onCreated(Bundle?) 에서 Fragment를 추가하는데, onActivityCreated(Bundle?) 함수는 Fragment가 추가된 후에 호출된다.
액티비티가 이미 실행 중일 때 프래그먼트를 추가하면 어떻게 될까?
이럴경우, FragmentManger는 해당 프래그먼트가 호스팅 액티비티의 상태를 따라잡는 데 필요한 프래그먼트 생명주기 함수를 몇개든 차례대로 즉시 호출한다. onAttach - onCreate - onCreateView - onActivityCreated - onStart - onResume 의 순서로 이 함수들의 호출을 연속으로 하여 받게 된다. 이렇게 하여 액티비티 상태와 동일해지면, 이후 부터는 호스팅 액티비티의 FragmentManager가 액티비티 상태와 동조된 프래그먼트 상태를 유지한다. (android OS 에서 액티비티 생명주기 함수가 호출되면, 이것과 부합된 프래그먼트 생명주기 함수들이 호출된다는 뜻이다.)
onCreate()
view에 대한 부분을 제외하고, fragment를 생성하면서 필요한 변수와 리소스를 초기화하는 부분.
onCreateView()
inflater를 이용하여 fragment의 view를 구성하는 부분이다.
fragment를 생성 시키기 위해 view를 레이아웃xml 로부터 띄우고 반환한다.
inflate()는 세개의 매개변수를 가진다.
1. 연결된 xml layout의 아이디값이 온다.
2. 해당 container가 어떠한 것이 들어갈지 결정한다.
3. false/true - root로 사용할지를 결정하는데, xml에 루트를 사용하므로 보통 False로 한다.
onActivityCreated()
activity의 oncreate() 가 반환될때, 호출
activity의 fragment의 view가 모두 생성된 상태이므로, View에 대한 작업을 여기서 처리한다.
onPause()
다른 Activity가 fragment의 부모 Activity위로 호출되면 onpause()를 호출하여
backstack으로 들어가게 한다.
onStop()
호출된 다른 Acitivity 가 완전히 화면을 가리면 onstop()이 호출,
사용자가 해당 Activity를 호출하면 다시 복원될 수 있는 상태이다.
onDestroyView()
onCrateView()에서 생성한 view가 Fragment에서 분리되었을 때, 호출
fragment를 다시 보여줘야할 때 새로운 view가 생성된다.
'Programming > Android' 카테고리의 다른 글
RecyclerView (0) | 2021.07.24 |
---|---|
JetPack (0) | 2021.07.22 |
app: build.gradle (0) | 2021.07.22 |