简体   繁体   English

有什么办法可以从应用程序组件dagger2访问贡献模块实例

[英]Is there any way to access contributing modules instances from application component dagger2

I have created a small sample to test dagger2 implementation. 我创建了一个小样本来测试dagger2的实现。 I have created a utility class in which an Activity's instance is to be injected. 我创建了一个实用程序类,其中将插入一个Activity的实例。 Is there any way to get this utility class instance in Activity itself using dagger2 有什么办法可以使用dagger2在Activity本身中获取此实用工具类实例

CoreApplication.kt CoreApplication.kt

class CoreApplication : Application(), HasActivityInjector {
    @Inject
    internal lateinit var dispatchingActivityInjector: DispatchingAndroidInjector<Activity>

    override fun activityInjector(): AndroidInjector<Activity> {
        return dispatchingActivityInjector    }

    val component: AppComponent by lazy {
        DaggerAppComponent
                .builder()
                .application(this)
                .sharedPreference(AppConstants.FILE_NAME_SHARED_PREFERENCES)
                .build()
    }
    override fun onCreate() {
        super.onCreate()
        component.inject(this)
        component.sharedPref().saveString("hello", "world")
        Log.i("test", component.sharedPref().getString("hello"))

    }
}

AppComponent.kt AppComponent.kt

@Singleton
@Component(modules = arrayOf(AndroidInjectionModule::class, ActivityBuilder::class, AppModuleBinds::class, AppModuleProvides::class))
interface AppComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application): Builder

        @BindsInstance
        fun sharedPreference(@Named(Constant.Name.SHARED_PREFERENCES) sharedPreferenceName: String): Builder

        fun build(): AppComponent

    }

    fun inject(application: CoreApplication)

    fun sharedPref() : SharedPreferenceUtils

}

ActivityBuilder.kt ActivityBuilder.kt

@Module
abstract class ActivityBuilder{
    @PerActivity
    @ContributesAndroidInjector(modules = arrayOf(HomeModuleBinds::class))
    abstract fun bindMainActivity(): MainActivity

    @PerActivity
    abstract fun dialogUtils() : DialogUtils

}

HomeModuleBinds.kt HomeModuleBinds.kt

@Module
    abstract class HomeModuleBinds {
        @Binds
        @PerActivity
        abstract fun activityContext(activity: Activity): Context

        @Binds
        @PerActivity
        abstract fun activity(activity: Activity): Activity
    }

DialogUtils.kt DialogUtils.kt

@PerActivity
class DialogUtils @Inject constructor(var activity: Activity) {
    fun showDialog(error: String) = {
        val alertDialogBuilder = AlertDialog.Builder(activity)
        alertDialogBuilder.setTitle(error).create().show()

    }
}

Is there any way I can use DialogUtils instance in MainActivity Using dagger2 dependency cycle? 有什么方法可以在MainActivity中使用drag2依赖周期使用DialogUtils实例吗?

class MainActivity : AppCompatActivity() {

    @Inject
    @Singleton
    lateinit var sharedPref : SharedPreferenceUtils

    @Inject
    @PerActivity
    lateinit var dialogUtils: DialogUtils

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        sharedPref.saveString("test", "val")
        Log.i("test", sharedPref.getString("test"))



        //dialogUtils.showDialog("hello")
    }
}

For example using inject for DaggerUtils on MainActivity is causing cyclic dependency error 例如,在MainActivity上对DaggerUtils使用Inject会导致循环依赖性错误

Don't inject the Activity into the Utility class. 不要将Activity注入Utility类。

Then in your Activity call: 然后在您的活动调用中:

dialogUtils.showDialog( "hello", MyACtivity.this)

In dialogUtils: 在dialogUtils中:

fun showDialog(error: String, context: Context) = {
        val alertDialogBuilder = AlertDialog.Builder(context)
        alertDialogBuilder.setTitle(error).create().show()

    }

Is there any way I can use DialogUtils instance in MainActivity Using dagger2 dependency cycle? 有什么方法可以在MainActivity中使用drag2依赖周期使用DialogUtils实例吗?

Yes, there is. 就在这里。 To do that, you'll have to do the following changes in your Dagger setup: 为此,您必须在Dagger设置中进行以下更改:

1. ActivityBuilder.kt 1. ActivityBuilder.kt

Delete the following lines: 删除以下行:

@PerActivity
abstract fun dialogUtils() : DialogUtils

Why? 为什么? You don't need it. 不用了 You already have DialogUtils injectable, since you annotated the class itself with @PerActivity and the constructor with @Inject . 您已经拥有DialogUtils可注入的了,因为您使用@PerActivity注释了类本身,并使用@Inject注释了构造函数。 Dagger will automagically do the required binding wherever DialogUtils is needed. Dagger将自动在需要DialogUtils地方进行所需的绑定。 You write provide/bind methods only when you're injecting an abstract type. 仅在注入抽象类型时才编写provide / bind方法。 In this case, DialogUtils is not implementing an abstract type that you inject in the Activity . 在这种情况下, DialogUtils不会实现您在Activity注入的抽象类型。 You inject the actual implementation directly so you don't need to setup any bindings. 您直接注入实际的实现,因此不需要设置任何绑定。

2. HomeModuleBinds.kt 2. HomeModuleBinds.kt

Change the Activity binding to more the specific Activity you want to bind to Activity , in this case it's MainActivity . 更改活动结合到更具体的Activity要结合Activity ,在这种情况下,它的MainActivity Dagger will then understand that it needs to bind it to Activity when DialogUtils asks for it. 然后,在DialogUtils提出要求时,Dagger将了解需要将其绑定到Activity You will need to do that for each Activity you want to use DialogUtils in the Activity 's own module - the one you pass as an argument to the @ContributeAndroidInjector(modules = [...]) , in this case it is HomeModuleBinds.kt . 您需要为要在该Activity自己的模块中使用DialogUtils的每个Activity执行此操作-您将其作为参数传递给@ContributeAndroidInjector(modules = [...]) ,在这种情况下为HomeModuleBinds。 kt

@Binds
@PerActivity
abstract fun bindMainActivity(mainActivity: MainActivity): Activity

3. DialogUtils 3. DialogUtils

The way you have method showDialog(String) defined currently, it returns a lambda! 当前定义方法showDialog(String)的方式,它返回一个lambda! Remove the equals = . 删除等于=

fun showDialog(error: String) {
    val alertDialogBuilder = AlertDialog.Builder(activity)
    alertDialogBuilder.setTitle(error).create().show()

}

4. MainActivity.kt 4. MainActivity.kt

Remove the scope annotations from the injected fields. 从注入的字段中删除范围注释。

@Inject
@Singleton // <-- Remove this
lateinit var sharedPref : SharedPreferenceUtils

@Inject
@PerActivity // <-- Remove this
lateinit var dialogUtils: DialogUtils

You can only annotate Components, Provide/Bind methods and classes with scope annotations! 您只能使用范围注释来注释组件,提供/绑定方法和类!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM