Fragment 생성시 newInstance() 사용하는 이유
1. 프래그먼트 재성성(화면 회전과 같은)시 빈 생성자가 있어야 한다
2. 재생성시 받아온 데이터를 유지하기 위해서 사용한다.
자주사용하는코드
companion object {
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
@JvmStatic
fun newInstance(param1: String, param2: String) =
MainFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
newInstance()방식은 빈생자를 만들고 bundle에 데이터를 넣어 처리해 주고 있다.
이렇게 함으로써 화면 회전과 같은 재사용이 되었을 때 받아온 데이터를 유지하며 화면에 보여줄 수 있다.
# 빈생성자 없으면 에러 발생
AndroidX부터는 다른 방식으로 초기화 해줘도 가능
AndroidX로 업데이트 되면서 기존에 사용하던 Fragment.instantiate()는 deprecated 되었다.
구글에서는 위 방식이 아닌 이제 FragmentFactory의 instantiate를 사용해 구현하라고 했다.
윕 방법을 사용하는 이유는 기존에는 프래그먼트에 빈 생성자가 없다면 구성 변경 및 앱의 프로세스 재성성과 같은 특정 상황에서 시스템은 프래그먼트를 초기화 하지 못했다.
이점을 해결하기 위해 FragmentFactory를 사용하게 되었고 Fragment에 필요한 인수 및 종속성을 제고하여 시스템이 Fragment를 더욱 잘 초기화하는데 도움을 준다.
AndroidX에서 인자가 있는 프래그먼트 생성 방법
1. 빈생성자 없이 인자가 있는 생성자를 만들어 준다.
class MainFragment(private val param1: String, private val param2: String) : Fragment() {
//...
}
2. FragmentFactory의 instantiate를 구현해 준다.
class MainFragmentFactoryImpl: FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return when (className) {
MainFragment::class.java.name -> MainFragment("black","jin")
else -> super.instantiate(classLoader, className)
}
}
}
3. MainActivity에서 다음과 같이 구현한다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
supportFragmentManager.fragmentFactory = MainFragmentFactoryImpl()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val fragment = supportFragmentManager.fragmentFactory.instantiate(classLoader, MainFragment::class.java.name)
supportFragmentManager.beginTransaction()
.replace(R.id.container_fragment, fragment)
.commitNow()
}
위 방법을 사용하면 Fragment.java에 있던 instatiate를 사용하지 않고 우리가 정의한 FragmentFactory의 instantiate 사용해 초기화를 하게된다.
여기서 중요한점
supportFragmentManager.fragmentFactory = FragmentFactoryImpl()
위 함수를 Activity의 onCreate보다 먼저 선언해 주어야 한다는 것이다
이렇게 하면 빈 생성자를 굳이 생성할 필요 없으며 bundle에 데이터를 넣지 않아도 재성성 상황에서 데이터가 보존된다.
FragmentFactory 꼭 필요한가?
그렇지 않다. 기존 방식대로 사용해도 무방하다. 다만 인자가 있는 생성자를 사용할 시 반드시 빈 생성자 프래그먼트를 만들어 주어야 한다.
Koin을 사용한 Fragment 초기화
FragmentFactory는 생성자를 주입하는 패턴과 비슷하다. 이에 안드로이드 의존성 주입 라이브러리 중 하나인 Koin에서는 위 방법을 지원해준다.
startKoin {
// setup a KoinFragmentFactory instance
fragmentFactory()
modules(...)
}
참고
https://black-jin0427.tistory.com/250
[Android, FragmentFactory] framgnet에서 newInstance() 쓰지 말라고?
안녕하세요. 블랙진입니다. 우리는 프래그먼트를 인자와 함께 생성할 때 newInstance()를 사용하곤 합니다. 왜 그럴까요? 흔히 알고 있는 두가지 이유가 있을 겁니다. 1. 프래그먼트 재생성(화면 회
black-jin0427.tistory.com
'안드로이드 > Fragment' 카테고리의 다른 글
fragment간 데이터 전송 (0) | 2022.10.03 |
---|---|
안드로이드 fragment에서 부모 fragment 접근 (0) | 2022.08.04 |
안드로이드 DialogFragment (0) | 2022.08.03 |
안드로이드 Activity Animation (0) | 2022.06.17 |
안드로이드 Fragment Animation (0) | 2022.06.17 |