๐กFragmentFactory์ ๋ํ์ฌ ํ์ตํ ๋ด์ฉ์ ๊ธฐ๋กํ์์ต๋๋ค.
FragmentFactory
- Android์์ Fragment ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ ์ปค์คํฐ๋ง์ด์งํ ์ ์๋ ํด๋์ค์ ๋๋ค.
- ๊ธฐ๋ณธ์ ์ผ๋ก Android Fragment๋ฅผ ํ๋ผ๋ฏธํฐ ์๋ ๊ธฐ๋ณธ ์์ฑ์๋ก ์์ฑํ์ง๋ง, ๊ฒฝ์ฐ์ ๋ฐ๋ผ Fragment๋ฅผ ์์ฑํ ๋ ์์กด์ฑ์ด๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฃผ์ ํด์ผ ํ ๋๊ฐ ์์ต๋๋ค.
- FragmentFactory๋ฅผ ์ฌ์ฉํ์ฌ Fragment์ ์์ฑ ๋ฐฉ์์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
- ViewModel ๋๋ Repository์ ๊ฐ์ ์์กด์ฑ์ Fragment์ ์ฃผ์ ํด์ผ ํ ๋ FragmentFactory๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ์์ ํ์ํ ์์กด์ฑ์ ์ฃผ์ ํ ์ ์์ต๋๋ค.
Fragment ์์ฑ์
- ์๋์ ๊ฐ์ด ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌ๋ฐ๋ Fragment๋ฅผ ์ ์ํ ๊ฒฝ์ฐ ์์ธ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
class MainFragment constructor(
private val tag: String,
): Fragment()
RuntimeException
- Fragment ์์ฑ์๋ฅผ ์ฐพ์ง ๋ชปํ๋ค๋ ๋ฐํ์ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
java.lang.InstantiationException: Unable to instantiate fragment
- ๊ณต์๋ฌธ์์์๋ Fragment๋ ์ธ์๊ฐ ํ๋๋ ์กด์ฌํ์ง ์๋ ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ํ์๋ก ํฌํจ๋์ด์ผํ๋ค๊ณ ๋ช ์๋์ด ์์ต๋๋ค.
All subclasses of Fragment must include a public no-argument constructor. The framework will often re-instantiate a fragment class when needed, in particular during state restore, and needs to be able to find this constructor to instantiate it. If the no-argument constructor is not available, a runtime exception will occur in some cases during state restore.
๋ฐ์ ์ด์ ๋ ๋ฌด์์ผ๊น?
- Fragment๋ ์๋ช
์ฃผ๊ธฐ์ ๋ฐ๋ผ์ ์๋๋ก์ด๋ ๋ด๋ถ์์ ํ๊ดด์ ์์ฑ์ ๋ฐ๋ณตํฉ๋๋ค.
- ํ๋ฉด ํ์ , ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํ์๋ ๊ด๋ จ์ด ์์ต๋๋ค.
- ๋ณต์ ๊ณผ์ ์์ FragmentManager์ ์ํด์ Fragment๋ฅผ ๋ณต์ํ๊ฑฐ๋ Bundle์ ํตํด ์ํ๋ฅผ ๋ณต์ํ ๋ ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- ์ด ๋ ํ๊ดด ํ ์ฌ์์ฑ๋๋ ๋จ๊ณ์์ ๋น ์์ฑ์๋ฅผ ํธ์ถํ๋ฉฐ, ๋น ์์ฑ์๋ฅผ ์ฐพ์ง ๋ชปํ๊ฒ ๋์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
Instantiate
public static Fragment instantiate(@NonNull Context context, @NonNull String fname,
@Nullable Bundle args) {
try {
Class<? extends Fragment> clazz = FragmentFactory.loadFragmentClass(
context.getClassLoader(), fname);
Fragment f = clazz.getConstructor().newInstance();
if (args != null) {
args.setClassLoader(f.getClass().getClassLoader());
f.setArguments(args);
}
return f;
}
...
}
- FragmnetFactory.loadFragmentClass()๋ getConstructor()๋ก ์์ฑ์๋ฅผ ๊ฐ์ ธ์ newInstance()๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
- ์์ฑ ๋ Fragment ์ธ์คํด์ค์ ์ ๋ฌํ Argument๋ฅผ ์ค๋ช ํ๊ณ ์ธ์คํด์ค๋ฅผ ๋ฆฌํดํฉ๋๋ค.
- ์ด ๋ getConstructor() ๊ณผ์ ์์ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์์ผ๋ฉด ์์ธ๋ฅผ ๋์ง๋๋ค.
FragmentFactory๋ฅผ ํ์ฉํ ์์กด์ฑ ์ฃผ์
- ์์กด์ฑ ์ฃผ์ ์ด๋ ํ๋ผ๋ฏธํฐ๊ฐ ํ์ํ ๊ฒฝ์ฐ FragmentFactory๋ฅผ ์ฌ์ฉํ์ฌ Fragment๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- ์ด ๋ฐฉ๋ฒ์ ํตํด์ Fragment์ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์๋๋ผ๋ ์ปค์คํ ํฉํ ๋ฆฌ๋ฅผ ํตํด ์์ฑ ๊ณผ์ ์ ์ ์ดํ ์ ์์ต๋๋ค.
class MyFragment(private val myDependency: MyDependency) : Fragment() {
// Fragment logic
}
class MyFragmentFactory(private val myDependency: MyDependency) : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return when (className) {
MyFragment::class.java.name -> MyFragment(myDependency)
else -> super.instantiate(classLoader, className)
}
}
}
- ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์ ๊ณตํ์ง ์๋๋ผ๋ FragmentFactory๋ฅผ ํตํด ์์กด์ฑ ์ฃผ์ ์ด ๊ฐ๋ฅํฉ๋๋ค.
Activity์์ FragmentFactory ์์ฑ
- ์กํฐ๋นํฐ์์ FragmentFactory๋ฅผ ์ค์ ํ์ฌ FragmentManager๊ฐ Fragment๋ฅผ ์์ฑํ ๋ ์ปค์คํ ํฉํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋๋ก ํฉ๋๋ค.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// FragmentFactory๋ฅผ ์ค์
val myDependency = MyDependency()
supportFragmentManager.fragmentFactory = MyFragmentFactory(myDependency)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Fragment ์ถ๊ฐ
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, MyFragment::class.java, null)
.commitNow()
}
}
}
์ ๋ฆฌ
- ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์๋ Fragment๋ฅผ ์์ฑํ๋ฉด ์๋๋ก์ด๋ ์์คํ ์ด Fragment๋ฅผ ์ฌ์์ฑํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- FragmentFactory๋ฅผ ์ฌ์ฉํ๋ฉด, ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ์์กด์ฑ ์ฃผ์ ์ ํตํด Fragment๋ฅผ ์์ฑํ ์ ์์ผ๋ฉฐ, ์์คํ ์์ ์ฌ์์ฑํ ๋๋ ๋ฌธ์ ์์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฐธ๊ณ
https://developer.android.com/reference/kotlin/androidx/fragment/app/FragmentFactory