Fragment는 무엇인가?
우리가 자주쓰는 카카오톡을 예로 들자
카카오톡 검정색 테두리 부분이 Activity 부분이다.
Activity안에 여러 Fragment를 만들어 넣을 수 있는 View공간을 만든다. (하얀공간)
오른쪽 사진에 있는 버튼들을 누르면 만들어둔 Fragment들을 View공간(하얀공간)에 넣어서 우리에게 보여주는 것이다.
Fragment를 왜 사용할까?
내가 가장 먼저든 의문은 Activity로 화면을 계속 넘기면 되는 거 아닌가?
왜 Fragment를 사용해야 할까? 라는 것이었다.
└ 이거에대한 답변 :
Activity로 화면을 계속 넘기는 것보다는 Fragment로 일부만 바꾸는 것이 자원 이용량이 적어
속도가 빠르기 때문에....
Fragment를 사용하면 Activity를 적게 만들 수 있다. = Activity의 복잡도를 줄일 수 있다.
Fragment를 사용하면 재사용할 수 있는 레이아웃을 분리해서 관리가 가능하다.
Fragment를 사용하면 최소 1개의 Activity안에서 Fragment공간에 View만 집어넣으면 여러 Activity를 만들지 않아도
우리에게 여러 화면을 보여줄 수 있다.
Fragment 특징
1. Fragment 자체로 우리에게 보일 수 없다.
만들어둔 Fragment 화면이 우리에게 보이기 위해서는 Activity 안에 존재해야 한다.
2. Fragment 만의 LifeCycle 이 존재한다.
3. 재사용이 가능하다.
Fragment LifeCycle(생명주기)
1. On Attach()
- Activity에 Fragment가 붙을 때 호출된다.
- Fragment가 완벽하게 생성된 상태는 아니다.
- 인자로 context가 주어진다.
2. On Create()
- Activity와 같이 초기화가 필요한 리소스들을 초기화한다.
- Fragment를 생성하면서 넘겨준 값이 있다면, 여기서 변수에 넣어준다.
- UI 초기화는 하지못한다.
- Activity의 onCreate()에서는 View나 UI 관련 작업을 할 수 있지만, Fragment onCreate()에서는 할 수 없다.
3. On CreateView()
- xml에 표기된 Layout들을 객체화해서 사용할 수 있게 해주는 곳.
- Layout객체를 얻을 수 있으므로, 버튼이나 텍스트뷰 등을 초기화 할 수 있다.
- View를 반환해여 한다. (UI를 제공하지않는 경우에는 Null을 반환하면 된다.)
- Fragment에 속한 View나 ViewGroup에 대한 UI 바인딩 작업을 할 수 있다.
- Fragment에서 UI를 그릴 때 호출되는 콜백이다.
- 매개변수 container는 Activity의 ViewGroup이며, 여기에 Fragment가 위치하게 된다.
- 매개변수 savedInstanceState는 Bundel 객체로 Fragment가 재개되는 경우 이전 상태에 대한 데이터를 제공한다.
4. On ActivityCreated()
- Fragment에서 onCreateView를 마치고, Activity에서 onCreate()가 호출되고 나서 호출된다.
- Activity와 Fragment의 뷰가 모두 생선된 상태로, View를 변경하는 작업이 가능한 단계이다.
- Activity에서 Fragment를 모두 생성하고 난 다음에 호출된다.
- Acitvity와 Fragment의 View가 모두 생성되고, 연결된 상태.
5. On Start()
- Fragment가 사용자에게 보여지기 직전 호출된다.
6. On Resume()
- Fragment가 화면에 보여지는 단계.
- 사용자와의 상호 작용이 가능하다. ex) 버튼클릭
- onPause() 되기 전까지는 이 단계에서 유지된다.
7. On Pause()
- Parent Activity가 아닌 다른 Activity가 위로 올라오거나, 다른 Fragment가 add되면서 포커스를 잃을때
일시정지 상태로 들어간다. - Fragment와 사용자의 상호작용이 중지된다.
- UI관련 처리를 정지하고, 중요한 데이터를 저장한다.
8. On Stop()
- Fragment가 완전히 가려지는 경우, onPause()에 이어 onStop() 까지 실행된다.
- Fragment는 더이상 보이지않고, Fragment 기능은 중지된다.
- 이 단계에서 시스템이 자동으로 onStateInstance()를 호출하여 UI의 상태를 저장하므로
Activity를 다시 띄우면 이전 상태 그대로 보인다.
9. On DestoryView()
- Fragment와 관련된 View가 제거될 때 실행된다.
- Activity에서 Fragment 생성 시 addToBackStack()을 요청했을 경우 onDestroy()를 호출하지 않고,
인스턴스가 저장되어 있다가 Fragment를 다시 부를 때 onCreateView()를 실행하여 다시 화면에 보여지게 한다.
10. On Destroy()
- View가 제거된 후 Fragment가 완전히 소멸되기 전에 호출된다.
11. On Detach()
- Fragment가 완전히 소멸되고, Activity와의 연결도 끊어질 때 실행된다.
Fragment 사용방법
★시작하기전에 Fragment KTX 를 사용하기 위해 build.gradle 에 다음과 같이 추가한다.
dependencies {
implementation("androidx.fragment:fragment-ktx:1.4.1")
}
위와 같이 작동하는 프로젝트를 만들어보자!
새로운 Activity만드는 방식과 비슷하다.
Fragment(Blank)를 누르고 이름을 지정한 다음 Finish를 누르면 된다.
Fragment를 총 2개 만든다.
이렇게 만들었다.
화면구성
*activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintBottom_toTopOf="@+id/fragment1_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginTop="10dp">
</FrameLayout>
<Button
android:id="@+id/fragment1_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Go Frag1"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/fragment2_btn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
<Button
android:id="@+id/fragment2_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Go Frag2"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/fragment1_btn"
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
여기서 볼 것은 Fragment를 사용하려면 FramLayout을 만들고 그 안에 넣어야 한다!
FrameLayout은 여러 화면을 쌓듯이(프레임 쌓듯이) 화면 위에 또 다른 화면을 가져와 띄울 수 있다.
*fragment_1.xml
간단하게 텍스트 뷰만 띄우기로 해요.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".Fragment1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This Frag1"
android:textAllCaps="false"
android:textSize="48sp"
android:background="@color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
*fragment_2.xml
fragment_1.xml 과 똑같이 만들어주고 Text만 "This Frag2" 로 수정하시면 됩니다.
Fragment 사용하기
*MainActivity.kt
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.run { // 1번
fragment1Btn.setOnClickListener{
setFragment(Fragment1()) //3번
}
fragment2Btn.setOnClickListener {
setFragment(Fragment2())
}
}
}
private fun setFragment(frag : Fragment) { //2번
supportFragmentManager.commit {
replace(R.id.frameLayout, frag)
setReorderingAllowed(true)
addToBackStack("")
}
}
}
코드분석
ViewBinding을 사용했습니다. (모르시면,,,검색!! 쉽습니다)
1번코드 : activity_main.xml 에 만든 버튼2가지 클릭이벤트 처리!
2번코드 : 함수를 하나 만들었습니다. 이 함수가 하는 역할은 파라미터로 사용할 Fragment를 받아와서
activity_main.xml에 만든 FrameLayout에 띄우는 간단한 함수입니다.
supportFragmentManager.commit {} : 사용자 상호작용에 응답해 Fragment를 추가하거나 삭제하는등 작업을
할 수 있게 해주는 매니저 라고 생각하시면 편합니다.
replace(R.id.frameLayout, frag) : replace(어느프레임 레이아웃에 띄울것이냐, 어떤프래그먼트냐)
어느프레임레이아웃에 띄울것이냐 : 아까 우리가만든 FrameLayout에 ID값 넣어줬죠? 그거 넣으시면됩니다.
어떤프래그먼트냐 : 우리가 함수를 만들때 프래그먼트를 인자로 받아왔죠? 그거 넣으시면됩니다.
setReorderingAllowed(true) : 애니메이션과 전환이 올바르게 작동하도록 트랜잭션과 관련된 프래그먼트의 상태 변경을 최적화 하는거 입니다. (사실 저도 잘 모릅니다.. 그냥 공식문서에서 쓰라고 했습니다!)
addToBackStack("") : 이 코드를 넣으면뒤로 가기버튼을 눌렀을 시에 차이가 있는데요.
이 코드를 추가하면 뒤로가기 버튼을 누를시 FrameLayout에 겹쳐져있던 그 전의 Fragment를 보여줍니다.
이 코드를 추가하지않으면 뒤로가기 버튼을 누를시 바로 앱이 종료됩니다. (한번추가하고 안하고 해서 실험해보세요!)
3번코드 : 이 코드는 버튼을 누르면 함수를 호출하는 간단한 코드입니다.
주의 깊게 볼 것은 함수를 호출할 때 무슨 값을 넘겨 줬는지입니다.
Fragment1() 과 Fragment2() 를 넘겨줬죠.
이겁니다. 잘보시면 Fragment1은 클래스 형식으로 만들어져있습니다. Fragment를 상속받았구요.
결국 우리가 함수를 호출할때 넘겨준것은 Fragment1 클래스를 객체화 해서 Fragment를 넘겨준것입니다.
Fragment1 클래스는 우리가 아까 만든 *fragment_1.xml 그겁니다.
setFragment(Fragment1()) = setFragment(어떤프래그먼트를 넘길거냐! 나는 Fragment1클래스를 객체화해서 만든 프래그먼트를 넘길것이다. !)
실행해 보시면 잘 될 것입니다..
제 부족한 설명력으로.. 이해시켜 드렸을지는 모르겠지만 글 읽어주셔서 감사합니다.
이해 안 가는 부분이 있으시거나 틀린 부분이 있으면 댓글 부탁드립니다.
참고사이트:
https://stackoverflow.com/questions/51614834/what-is-lifecycle-of-dialogfragment
https://asong-study-record.tistory.com/69
https://readystory.tistory.com/199
'Android-Kotlin > Android' 카테고리의 다른 글
[Android] DataClass 란? (0) | 2022.06.25 |
---|---|
[Android] RecyclerView 개념 및 사용방법 - Kotlin (2) | 2022.06.23 |