Dagger2可以提供活动依赖于匕首

发布于 2025-01-28 08:49:24 字数 1867 浏览 2 评论 0原文

没有@Inject构造函数或 @提供通知的方法。这种类型支持会员注射,但 不能隐式提供。

我正在使用匕首android,我通过androidivect.iment(this)注入了主动,但在模块中仍然无法使用。我准备了示例项目: https://github.com/github.com/deepsorory/testsororcor/test_daggersusissu.git.git.git.git 下面列出:

FactoryVmmodule:

@Module
class FactoryVmModule {

    @Provides
    @Named("TestVM")
    fun provideTestVM(
        activity: MainActivity, // <--- dagger can't inject this
        viewModelFactory: ViewModelFactory
    ): TestVM =
        ViewModelProvider(activity, viewModelFactory)[TestVM::class.java]

}

MainActivityModule:

@Module
abstract class MainActivityModule {
    @ContributesAndroidInjector
    abstract fun injectMainActivity(): MainActivity
}

MainActivity(使用DaggerAppCompatactivity):

class MainActivity : DaggerAppCompatActivity() {

    @Named("TestVM")
    @Inject
    lateinit var testVM: TestVM

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

TestApplication:

class TestApplication : Application(), HasAndroidInjector {
    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>

    override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.create().inject(this)
    }

    override fun androidInjector() = dispatchingAndroidInjector
}

AppComponent:

@Component(modules = [AndroidInjectionModule::class, MainActivityModule::class, ViewModelModule::class, FactoryVmModule::class])
interface AppComponent {
    fun inject(application: TestApplication)
}

MainActivity cannot be provided without an @Inject constructor or an
@Provides-annotated method. This type supports members injection but
cannot be implicitly provided.

I'm using dagger-android, I injected MainActivity through AndroidInjection.inject(this), but it's still unavailable in Module. I prepared sample project: https://github.com/deepsorrow/test_daggerIssu.git, files listed below:

FactoryVmModule:

@Module
class FactoryVmModule {

    @Provides
    @Named("TestVM")
    fun provideTestVM(
        activity: MainActivity, // <--- dagger can't inject this
        viewModelFactory: ViewModelFactory
    ): TestVM =
        ViewModelProvider(activity, viewModelFactory)[TestVM::class.java]

}

MainActivityModule:

@Module
abstract class MainActivityModule {
    @ContributesAndroidInjector
    abstract fun injectMainActivity(): MainActivity
}

MainActivity (using DaggerAppCompatActivity):

class MainActivity : DaggerAppCompatActivity() {

    @Named("TestVM")
    @Inject
    lateinit var testVM: TestVM

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

TestApplication:

class TestApplication : Application(), HasAndroidInjector {
    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>

    override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.create().inject(this)
    }

    override fun androidInjector() = dispatchingAndroidInjector
}

AppComponent:

@Component(modules = [AndroidInjectionModule::class, MainActivityModule::class, ViewModelModule::class, FactoryVmModule::class])
interface AppComponent {
    fun inject(application: TestApplication)
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

抚你发端 2025-02-04 08:49:24

dagger.android /dagger.dev/dev-guide/android.html#injecting-activity-objects“ rel =” nofollow noreferrer“> explicit版本 @contributesandroidInjector 为您生成,其中生成 androidInjector.factory.factory @bindsinstance binding 您在此处请求的类型。

这对您不起作用,因为您正在将MainActivity注入安装在顶级组件上的绑定中。这是一个问题,因为AppComponent将在活动之前存在,并且还将替换为Android重新创建活动:通过@component.builder not 围绕这个问题。

相反,将factoryvmmodule :: class移动到子组件中,@contributesandroidInjector生成,您可以通过将其包括在

@Module
abstract class MainActivityModule {
    @ContributesAndroidInjector(
        modules = [ViewModelModule::class, FactoryVmModule::class]
    )
    abstract fun injectMainActivity(): MainActivity
}

我也将您的ViewModelModule类移动到其中;尽管如果不取决于活动的任何内容,您可能会将其放在顶级组件中,但您可能需要将它们保持在一起。子组件中的绑定从应用程序继承,因此您可以从活动的子组件中注入AppComponent级的绑定,但相反的绑定。这意味着您将无法在活动之外注入VM实例(这里,TestVM),但是如果它们依赖于活动,您都不会想:这些实例可能会陈旧,并防止垃圾收集者收回您的收回完成的活动实例。

dagger.android does do this automatically: See the explicit version of the binding that @ContributesAndroidInjector generates for you, where the generated AndroidInjector.Factory contains a @BindsInstance binding of the type you request here.

This isn't working for you because you are injecting MainActivity in a binding that is installed on your top-level component. This is a problem because AppComponent will exist before the Activity does, and will also be replaced as Android recreates the Activity: Passing an instance through @Component.Builder is not a way around this problem.

Instead, move your FactoryVmModule::class to within the subcomponent that @ContributesAndroidInjector generates, which you can do by including it in the modules attribute on @ContributesAndroidInjector. Dagger will create a different subcomponent instance per Activity instance, so your FactoryVmModule will always have a fresh binding to MainActivity.

@Module
abstract class MainActivityModule {
    @ContributesAndroidInjector(
        modules = [ViewModelModule::class, FactoryVmModule::class]
    )
    abstract fun injectMainActivity(): MainActivity
}

I moved your ViewModelModule class there as well; though it's possible you could leave it in your top-level Component if it doesn't depend on anything belonging to the Activity, you might want to keep them together. Bindings in subcomponents inherit from the application, so you can inject AppComponent-level bindings from within your Activity's subcomponent, but not the other way around. This means you won't be able to inject VM instances (here, TestVM) outside your Activity, but if they depend on the Activity, you wouldn't want to anyway: Those instances might go stale and keep the garbage collector from reclaiming your finished Activity instances.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文