ViewModelFactory と同じような感じで FragmentFactory および Fragment の生成をまかせることができます。
オブジェクトグラフに MyApi があるとします。
@Module
object AppModule {
@Provides
fun provideMyApi(): MyApi {
...
}
}
これを引数にとる Fragment があります。Dagger に生成をまかせたいのでコンストラクタに @Inject をつけます。
class MainFragment @Inject constructor(private val api: MyApi) : Fragment() {
...
}
Fragment の Map Multibindings 用の MapKey を用意します。
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class FragmentKey(val value: KClass<out Fragment>)
用意した MapKey を使って MainFragment を Multibindings に追加します。
@Module
interface FragmentModule {
@Binds
@IntoMap
@FragmentKey(MainFragment::class)
fun bindMainFragment(fragment: MainFragment): Fragment
}
Fragment の Multibindings を引数に取る FragmentFactory を用意します。
class MyFragmentFactory @Inject constructor(
private val providers: Map<Class<out Fragment>, @JvmSuppressWildcards Provider<Fragment>>
) : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
val found = providers.entries.find { className == it.key.name }
?: throw IllegalArgumentException("unknown model class $className")
val provider = found.value
try {
@Suppress("UNCHECKED_CAST")
return provider.get()
} catch (e: Exception) {
return super.instantiate(classLoader, className)
}
}
}
用意した MyFragmentFactory を取得するためのメソッドを Component に用意します。
@Component(modules = [AppModule::class, FragmentModule::class])
interface AppComponent {
fun fragmentFactory(): MyFragmentFactory
}
class MyApplication : Application() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.builder()
.build()
}
}
supportFragmentManager.fragmentFactory に Component から取得した MyFragmentFactory をセットします。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportFragmentManager.fragmentFactory = (application as MyApplication).appComponent
.fragmentFactory()
setContentView(R.layout.activity_main)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainFragment"
android:name="net.yanzm.sample.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
0 件のコメント:
コメントを投稿