我有Dagger 2配置:
AppComponent.kt
static IntPtr pointer;
public void UnmanagedAllocation()
{
pointer = Marshal.AllocHGlobal(1024 * 1024 * 1024 );
}
ActivityBindingModule.kt
-- Usage Summary RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 59 762f7000 ( 1.847 GB) 46.17%
<unknown> 98 4493e000 ( 1.072 GB) 49.76% 26.79%
Heap 15 40158000 ( 1.001 GB) 46.50% 25.03%
Image 174 2db2000 ( 45.695 MB) 2.07% 1.12%
MappedFile 15 1c51000 ( 28.316 MB) 1.28% 0.69%
Stack 24 800000 ( 8.000 MB) 0.36% 0.20%
MainActivityModule.kt
@Singleton
@Component(
modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
ActivityBindingModule::class,
]
)
interface AppComponent : AndroidInjector<AppApplication> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<AppApplication>()
}
FragmentModule.kt
@Module
abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector(
modules = [
MainActivityModule::class,
FragmentModule::class //a fragment factory for each activity
]
)
internal abstract fun mainActivity(): MainActivity
}
DefaultFragmentFactory.kt
@Module(subcomponents = [LoginFragmentSubcomponent::class])
abstract class MainActivityModule {
//uncommenting this works fine but Fragment can't be scoped
//@Binds
//@IntoMap
//@FragmentKey(LoginFragment::class)
//abstract fun bindLoginFragment(loginFragment: LoginFragment): Fragment
//...other things which work fine
}
@Subcomponent(modules = [LoginFragmentModule::class])
@FragmentScoped
interface LoginFragmentSubcomponent : AndroidInjector<LoginFragment> {
@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<LoginFragment>()
}
@Module
abstract class LoginFragmentModule {
//this can't be seen from Map used in DefaultFragmentFactory
@Binds
@IntoMap
@FragmentKey(LoginFragment::class)
abstract fun bindLoginFragment(loginFragment: LoginFragment): Fragment
}
我在这里想要做的是使用@Module
abstract class FragmentModule {
@Binds
internal abstract fun bindFragmentFactory(factory: DefaultFragmentFactory): FragmentFactory
}
创建@ActivityScoped
class DefaultFragmentFactory @Inject constructor(
private val creators: Map<Class<out Fragment>, @JvmSuppressWildcards Provider<Fragment>>
) : FragmentFactory() {
//this is deprecated in fragment-ktx 1.1.0-alpha06
//but you need to override this if you were using the bundle
override fun instantiate(classLoader: ClassLoader, className: String, args: Bundle?): Fragment {
return instantiate(classLoader, className).apply { arguments = args }
}
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
val fragmentClass = loadFragmentClass(classLoader, className)
val found = creators.entries.find { fragmentClass.isAssignableFrom(it.key) }
val provider = found?.value
//if we don't find a match in the map, proceed with the default empty constructor
return if (provider != null) {
provider.get()
} else {
fragmentClass.newInstance()
}
}
}
。
如代码中所述,我可以取消注释以下行:
FragmentFactory
并删除与Fragments
连接的所有内容,注入工作正常。
此方法的问题在于,无法正确划分Fragment的范围,如果Fragment被销毁,则以下所有子Fragment都将销毁,这将迫使Factory在下一次调用时创建新实例。
因此,我决定添加一个名为LoginFragmentSubcomponent的@Binds
@IntoMap
@FragmentKey(LoginFragment::class)
abstract fun bindLoginFragment(loginFragment: LoginFragment): Fragment
以便能够在其上定义LoginFragmentSubcomponent
。
现在的问题是,在Subcomponent
中,我无法从模块@FragmentScoped
中为我需要的父LoginFragmentModule
做出贡献,
Map
事实上,我在编译时收到的错误是:
DefaultFragmentFactory
此处有一个带有可重现问题的示例存储库:shx
我该如何解决? 我确定我做错了什么,因为我仍在学习Dagger 2和/或我不了解问题的某些部分以及它应该如何工作。
使用匕首2.21
预先感谢
PS:
Map<Class<out Fragment>, @JvmSuppressWildcards Provider<Fragment>>
注入背后的想法来自于 很棒的帖子: https://github.com/matpag/dagger-test-fragmentfactory我只是稍作调整。