일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- Button
- 테스트
- drift
- binding
- tabbar
- appbar
- 계측
- 앱바
- ScrollView
- CustomScrollView
- android
- textfield
- Navigation
- data
- Flutter
- LifeCycle
- Compose
- activity
- 앱
- DART
- TEST
- Coroutines
- textview
- intent
- livedata
- scroll
- Dialog
- Kotlin
- viewmodel
- 안드로이드
- Today
- Total
Study Record
[안드로이드] Fragment 살펴보기 본문
😶 Fragment
Fragment 는 앱 화면에서 사용자와 상호작용할 수 있는 한 부분으로 ViewGroup 에 속한다. Activity 에 여러 개의 Fragment 가 존재할 수 있고 여러 개의 Activity 에 하나의 Fragment 를 재사용할 수 있다. 항상 Activity 내에서 호스팅 되어야 한다.
자체 생명 주기를 가지고 자체 입력 이벤트를 수신하며 Activity 실행 중 추가 및 삭제가 가능하다. Activity 가 관리하는 백 스택에도 Fragment 를 추가할 수 있다. (ex. 뒤로 가기 버튼을 누르면 액티비티가 종료하는 것이 아닌 이전 Fragment 가 나오는 경우)
😶 Fragment 수명주기
프래그먼트의 수명 주기는 왼쪽 그림과 같다. 그 중 최소한 구현해야 하는 수명 주기를 살펴보면 onCreate() , onCreateView() , onPause() 가 있다.
onCreate()
프래그먼트를 생성할 때 시스템에서 호출하는 매서드로 프래그먼트가 일시정지되거나 중단되었다 재개되었을 때 유지하고자 하는 것을 초기화한다.
onCreateView()
사용자 인터페이스를 처음으로 그릴 때 호출되는 매서드로 return 값으로 화면에 그려질 View 를 반환해야 한다. null 을 반환할 경우 프래그먼트의 UI 를 제공하지 않는다는 의미가 된다.
onViewCreated()
View 가 생성된 후 호출되는 메서드로 여기서 일반적으로 findViewById 함수를 호출한다.
onPause()
프래그먼트가 소멸하기 전, 사용자가 프래그먼트를 사용하지 않을 때 호출된다. 사용자가 다시 프래그먼트로 돌아올수도, 돌아오지 않을 수도 있다.
onActivityCreated()
Activity 의 onCreate() 메서드가 반환될 때 호출된다.
onDetach()
Fragment 가 Activity 와 연결이 끊어지는 중일 때 호출된다.
😶 Fragment State
INITIALIZED : 프래그먼트의 새 인스턴스가 인스턴스화됨
CREATED : 첫 프레그먼트 라이프사이클 메서드가 호출됨. 이 상태 동안 프레그먼트와 뷰가 상호작용하기 시작됨.
STARTED : 프래그먼트가 화면에 보이기 시작했을 때로 아직 focus 는 얻지 못함. 사용자와 상호작용 불가능.
RESUED : 프래그먼트가 화면에 보이고 focus 를 얻은 상태.
DESTORYED : 프래그먼트 객체가 해제됨.
수명 주기 메서드와 State 와의 관계
Lifecycle State | Fragment Callback |
CREATE | onCreate(), onCreateView(), onViewCreated() |
STARTED | onStart() |
RESUMED | onResume() |
STARTED | onPause() |
CREATED | onStop(), onDestoryView() |
DESTORYED | onDestory() |
😶 Fragment 시작하기
ExampleFragment 를 MainActivity 에 연결하기
Fragment 의 xml 파일(fragment_example.xml)을 만들고 Fragment 클래스를 상속받는 ExampleFragment 클래스를 만든다. 이 예시는 데이터 바인딩을 사용한다.
class ExampleFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
// return inflater.inflate(R.layout.fragment_example, container, false)
val binding = DataBindingUtil.inflate<FragmentExampleBinding>(
inflater,
R.layout.fragment_example,
container,
false,
)
return binding.root
}
companion object {
@JvmStatic
fun newInstance(param1: String, param2: String) =
ExampleFragment()
}
Fragment 를 Activity 에 연결하는 2가지 방법이 있는데 한가지는 xml 코드에서 바로 연결하는 것이고, 나머지 하나는 프로그래밍 방식으로 프래그먼트를 ViewGroup 에 추가하는 방법이다.
1. xml 코드에서 바로 연결하는 방법
FragmentContainerView 태그의 android:name 속성에 연결할 Fragment 클래스를 입력한다.
<?xml version="1.0" encoding="utf-8"?>
<layout>
<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">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/main_fg"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="com.example.basic_text.ExampleFragment"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
2. 프로그래밍 방식으로 프래그먼트를 기존의 ViewGroup 에 추가한다.
Activity 내에서 프래그먼트 트랜잭션(추가, 제거, 교체)을 사용하여 추가한다.
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
// 프래그먼트 추가
with(supportFragmentManager.beginTransaction()) {
add(binding.mainFg.id, ExampleFragment())
commit()
}
}
}
😶 프래그먼트 관리 (FragmentManager)
Activity 에서 Fragment 를 관리하려면 FragmentManager 를 사용해야 한다. 이것은 Activity 에서 supportFragmentManager 로 불러올 수 있다.
FragmentManager 에서 불러올 수 있는 트랜잭션(Transaction)이 있는데 이 트랜잭션은 수행하고자 하는 변경사항의 집합니다. 즉, xml 에 정의한 프래그먼트 태그에 어떤 프래그먼트를 연결할지와 같은 변경사항들을 수행할 수 있다. 이렇게 변경사항들(Transaction)을 적용하려면 commit() 을 호출하면 된다.
val newFragment = ExampleFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.add(R.id.fragment_container, newFragment)
transaction.commit()
프래그먼트를 교체하려면 transaction.replace() 함수를 사용하면 되는데 이 때 commit() 을 호출하기 전 addToBackStack() 을 호출하면 백 스택에 프래그먼트 정보를 저장하여 사용자가 Back 버튼을 누를 때 자동으로 이전 프래그먼트를 가져올 수 있다.
val newFragment = ExampleFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, newFragment)
transaction.addToBackStack(null)
transaction.commit()
만약 현재 프래그먼트를 제거하는 트랜잭션을 수행하면서 addToBackStack() 를 사용하지 않으면 해당 프래그먼트는 소멸되고 사용자가 탐색할 수 없게 된다.
commit() vs commitAllowingStateLoss()
트랜잭션을 커밋할 때 commit() 을 호출하더라도 즉시 트랜잭션이 실행되지 않고 Activity 의 UI 스레드에 이 트랜잭션이 수행되도록 예약하는 것에 가깝다. commit() 을 사용할 수 있는 것은 Activity 가 상태를 저장하기 전뿐이고 이 이후에 커밋하려고 하면 예외가 발생한다.
예외가 발생하는 이유는 Activity 를 복원해야 하는 경우 커밋 이후의 상태가 손실될 수 있기 때문이다. 손실되어도 괜찮다면 commitAllowingStateLoss() 를 사용할 수 있다.
😶 Activity 와의 통신
Fragment 에서 Activity 참조
간단하게 Fragment 에서 activity 로 참조하는 Activity 를 가져올 수 있다.
(activity as MainActivity)
Activity 에서 Fragment 참조
findFragmentById() 혹은 findFragmentByTag() 함수로 id 혹은 tag 로 Fragment 에 접근할 수 있다.
(supportFragmentManager.findFragmentById(binding.mainFg.id) as ExampleFragment)
'안드로이드' 카테고리의 다른 글
[안드로이드] 앱바 Menu 추가하기 (+ Navigation) , drawer (0) | 2023.06.25 |
---|---|
[안드로이드] Navigation (탐색) 살펴보기 (0) | 2023.06.25 |
[안드로이드] 데이터 바인딩(Data binding)과 뷰 바인딩(View binding) (0) | 2023.06.19 |
[안드로이드] ConstraintLayout 살펴보기 (0) | 2023.06.17 |
[안드로이드] 키보드 내리기/올리기/Activity 시작 시 자동으로 올리기 (0) | 2023.06.16 |