안드로이드 With Java #18 Fragment
Activity
내의 사용자 인터페이스의 일부를 나타낸다. Activity
의 일부 구성 요소를 Fragment
로 대체 가능하다. Activity
내부에서 보여줄 것이 많을 때 사용한다.
만들어놓은 Fragment
를 여러 Activity
에서 사용 가능하다. 그래서 반복적으로 여러 가지를 만들어야 하는 작업을 효율적으로 가능하다.
Activity
내에 포함되어 있어야 한다.Activity
라이프 사이클에 직접적으로 영향을 받는다.Fragment
가 UI를 가지고 있어야 하는 것은 아니다.위와 같은 라이프사이클을 갖는다.
Fragment
라이프사이클은 Activity
라이프사이클에 직접적으로 영향을 받는다.
onAttach
Fragment
가 Activity
와 연관되어 있었던 경우 호출된다. (Activity
가 전달된다.)onCreateView
Fragment
가 자신의 사용자 인터페이스를 처음으로 그릴 때 호출된다.onActivityCreated
Activity
의 onCreate()
가 반환되면 호출된다.onDestroyView
Fragment
와 연관된 뷰 계층이 쩨거되는 중일 때 호출된다.onDetach
Fragment
가 Activity
와 연결이 끊어지는 중일 때 호출된다.Fragment
를 특정 뷰에 할당한다.Fragment
를 xml에 등록한다.FragmentManager
를 통해 관리하다.Fragment
를 떼거나 붙이거나 할 수 있다. Fragment
를 찾는 작업도 가능하다.MainActivity
의 Layout
에 Fragment
가 들어갈 LinearLayout
을 한개 더 넣고 거기에 새롭게 xml
로 정의한 Fragment
를 넣는 작업을 해보자.
LinearLayout
내부에 LinearLayout
을 넣어줬다. id
는 container
로 지정해주었고, 크기는 match_parent
인데 height
만 100dp
로 지정해주었다.
fragment
의 영역을 확실히 알기 위해서 background
속성만 주었다.
위와 같이 생성하면 되는데,
extends Fragment
부분이 Fragment
클래스를 상속받게 해주어 일반 클래스를 Fragment
로 인식하게 해준다.
그리고 라이프사이클 중 onCreateView()
를 오버라이드하여 내부에 xml로 정의해둔 Fragment
가 그려지게 만들면 된다.
LayoutInflater
가 xml을 그리는 역할을 한다.
공식문서의
Inflater
설명에는 간단하게Layout
xml 파일을 받아 View 클래스로 변환시켜준다고 나와있다.
View view = inflater.inflate(R.layout.fragment_one, container, false);
위와 같이 작성하고 view
를 반환하면 된다.
Fragment
의 영역을 적용하기 위해서는 FragmentManager
를 먼저 생성해주어야 한다. FragmentManager
는 getSupportFragmentManager()
메소드를 통하여 불러올 수 있다.
그 다음에는 FragmentManager
클래스에서 제공하는 beginTransaction()
메소드를 이용하여 FragmentTransaction
클래스의 인스턴스를 생성해준다.
FragmentTransaction
클래스의 add()
메소드를 통하여 지정된 영역에 Fragment
클래스를 넣어줄 수 있다. 단, add()
메소드는 작업을 추가하는 역할이고 실제 수행은 commit()
메소드를 수행해야 시작된다.
이번에는 버튼을 눌렀을 때 Fragment
를 교체하는 작업을 해보자.
background
에 이전과 다른 색을 줘서 변화했을 때 구분이 가게 만들었다.
아까와 마찬가지로 Fragment
클래스를 상속시키고, inflater.inflate()
메소드를 이용하여 이전에 만든 Layout
xml을 View
로 만들어 반환했다.
버튼을 누르면 교체되도록 하기 위해 버튼을 만들었다.
findViewById()
메소드를 이용하여 onClickListener
를 달아주고, 새로운 FragmentTransaction
을 만들어주었다. FragmentTransaction
은 한번 commit()
하게되면 유통기한이 만료되기 때문에 새로 만들어주어야 한다.
MainActivity
의 onStart
시점에서 FragmentOne
의 라이프사이클이 시작되고 FragmentOne
이 onStart
까지 마무리 했을 때, MainActivity
의 라이프사이클도 다시 재개된다.
그리고 MainActivity
가 onResume
이 되면 FragmentOne
도 onResume
된다.
FragmentTwo
의 onAttach
가 수행되면서 시작한다. FragmentTwo
의 onCreate
이후에 사라질 FragmentOne
은 onPause
부터 onDetach
까지 차례로 진행하며 사라진다.
그리고 이후에는 FragmentTwo
가 onCreateView
부터 onResume
까지 수행하며 생성된다.
MainActivity
의 라이프사이클은 관여하지 않는다.
위와 같이 기존에 LinearLayout
이나 TextView
를 추가하던 것처럼 그냥 xml에 추가하면 된다. 단, fragment
태그는 앞이 소문자임을 유의하자.
id
속성은 fragment
에 반드시 필요하다. name
속성은 Fragment
클래스를 참조할지에 대한 내용이다.
name
속성에 들어갈 Fragment
가 반드시 필요하므로, Fragment
를 xml에서 직접 추가하더라도 클래스를 만들고 Fragment
클래스를 상속하게 하고 onCreateView()
콜백 함수에서 LayoutInflater
를 이용하여 View
를 반환하는 작업까지는 다 해주어야 한다.
실행결과 두개의 Fragment
가 잘 붙었다.
기본적으로는 자유이나 동적으로 다루고 싶을 때는 Java로 붙이는 편이 좋다.
Fragment를 한번 만들어놓고 여러 Activity에서 사용하고 싶을 때는 xml에 Fragment를 직접 등록하는 편이 좀 더 좋을 수 있다.
onActivityCreated
라이프 사이클에서 수행하는 편이 좋다. 왜냐하면 이전 라이프사이클에서는 Activity
의 존재 자체가 보장받지 못할 수 있다. 그렇게 되면 참조하려는 버튼과 같은 요소가 생성 전일 수 있기 때문에 onAcitivityCreated
에서 하는 것이 좋다.
위와 같은 방식으로 하면 된다.
이 때 사용되는 View
클래스는 getView()
메소드로 얻어와도 무관하고, 다음과 같이 전역에서 미리 view
변수를 선언해두었다가 inflater
가 inflate
로 View
를 생성할 때 얻어와도 된다.
이전에 Activity
에서 Intent
를 이용해 값을 넘길 때는 putExtra()
메소드를 이용했었다. Fragment
에서는 Bundle
을 사용한다.
Bundle
인스턴스를 생성하고, put자료형
형태의 메소드를 이용하여 key
, value
형식으로 값을 넣는다.
그리고 Fragment
객체에 setArguments()
메소드를 통하여 만든 bundle
을 주입한다.
위와 같이 확인하면 된다.
Fragment
에서 추가적인 로직을 수행할 때는 onActivityCreated()
에서 수행하는 것이 안전하다.
getArguments()
로 Fragment
에 전해진 Bundle
을 받아올 수 있고 get자료형
메소드로 값을 가져올 수 있다.
로그 확인 결과 이상없이 잘 작동한다.
일반적으로는 String
형태인 Key
를 중구난방으로 설정하면 까먹거나 매번 찾게되므로 저렇게 선언해두는 경우가 많다.
다른 클래스에서 찾을 때도.
이렇게 작성하고 빨간줄이 나왔을 때 Alt+Enter
를 이용하여 쉽게 찾을 수 있다.