我有一个模型(AModel),我想用作单例。我创建了一个名为 @ApplicationScope 的自定义范围,以便将它用于我只需要一次的每个类。所以 AppComponent 和 AModel 共享这个 @ApplicationScope。我有一些 fragment (ConfirmationFragment),我想同时使用 AModel 和 BModel。 BModel 具有不同的范围,因为我想在 3 个 fragment 中使用它,但 Amodel 到处都需要。
访问 AModel 和 BModel 的想法是让 ConfirmationComponent 依赖于 AModel 已经可用的 AppComponent。这样,如果我将 ConfirmationComponent 注入(inject) ConfirmationFragment,我也可以使用 AModel。
但我收到以下错误:[Dagger/IncompatiblyScopedBindings] ConfirmationComponent scoped with @ConfirmationScope may not reference bindings with different scopes:
当从 ConfirmationFragment 中注释掉注入(inject) AModel 时构建成功,但在没有注释时失败。我也需要那个 fragment 中的 AModel。
我该如何解决这个问题?
(以防它很重要:我只使用一个 Activity ,并让 Android 导航处理 fragment 。)
open class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
val appComponent = initializeComponent()
}
val appComponent: AppComponent by lazy {
initializeComponent()
}
val confirmationComponent: ConfirmationComponent by lazy {
initializeConfirmationComponent()
}
open fun initializeComponent(): AppComponent {
return DaggerAppComponent.factory().create(applicationContext)
}
open fun initializeConfirmationComponent(): ConfirmationComponent {
return DaggerConfirmationComponent.builder().appComponent(appComponent).build()
}
}
@ApplicationScope
@Component(modules = [NetworkModule::class])
interface AppComponent {
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context) : AppComponent
}
fun inject(activity: MainActivity)
fun inject(fragment: ConfirmationFragment)
}
@ConfirmationScope
@Component(dependencies = [AppComponent::class])
interface ConfirmationComponent {
fun inject(fragment: ConfirmationFragment)
}
@ApplicationScope
class AModel @Inject constructor() {}
@ConfirmationScope
class BModel @Inject constructor() {}
class ConfirmationFragment : Fragment() {
@Inject
lateinit var modelA : AModel
@Inject
lateinit var modelB : BModel
override fun onAttach(context: Context) {
super.onAttach(context)
(requireActivity().applicationContext as MyApplication).confirmationComponent.inject(this)
}
// Rest of the code
}
最佳答案
我认为你应该换一种方式。如果我的理解正确,ModelA 的范围比 ModelB 大,这意味着您可以将 ModelB 作为 ModelA 的子组件,但范围更窄。
所以为此你需要:
//@YourScopeAnnotation
@Subcomponent(modules = [...]) // if it is dependent on any modules
interface ConfirmationComponent {
// needed for dagger to create component
@Subcomponent.Factory
interface Factory {
fun create(): ConfirmationComponent
}
fun inject(yourFragment: Fragment) // fun inject your fragment
}
@Module(
subcomponents = [ConfirmationComponent::class]
)
class SubcomponentsModule
//@ApplicationScopeAnnotation I think you can also use @Singleton
@Component(
modules = [NetworkModule::class, SubcomponentsModule::class]
)
interface ApplicationComponent {
fun inject(activity: MainActivity)
fun confirmationComponent(): ConfirmationComponent.Factory
}
@Inject
lateinit var modelA : AModel
lateinit var confirmationComponent: ConfirmationComponent
override fun onCreate(savedInstanceState: Bundle?) {
confirmationComponent = (applicationContext as MyApplication).appComponent
.confirmationComponent()
.create()
modelA = (applicationContext as MyApplication).appComponent.inject(this)
}
@Inject
lateinit var modelB: ModelB // inject modelB
lateinit var modelA: ModelA // get ModelA from activity where it was already injected
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
(activity as MainActivity).confirmationComponent.inject(this)
modelA = (activity as MainActivity).modelA
}
我希望这有帮助 :)
关于android - 如何解决不同范围的绑定(bind)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61289968/