有没有办法从应用程序组件dagger2访问贡献模块实例

时间:2018-06-13 16:45:29

标签: android dependency-injection kotlin dagger-2 dagger

我创建了一个小样本来测试dagger2的实现。我创建了一个实用程序类,其中将注入Activity的实例。有没有办法使用dagger2

在Activity本身中获取此实用程序类实例

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

@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

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

    @PerActivity
    abstract fun dialogUtils() : DialogUtils

}

HomeModuleBinds.kt

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

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

DialogUtils.kt

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

    }
}

有没有办法在MainActivity中使用DialogUtils实例使用dagger2依赖循环?

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")
    }
}

例如,在MainActivity上使用inject for DaggerUtils会导致循环依赖性错误

2 个答案:

答案 0 :(得分:0)

不要将Activity注入Utility类。

然后在你的活动电话中:

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

在dialogUtils中:

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

    }

答案 1 :(得分:0)

  

有什么方法可以使用dagger2依赖周期在MainActivity中使用DialogUtils实例吗?

是的,有。为此,您必须在Dagger设置中进行以下更改:

1。 ActivityBuilder.kt

删除以下几行:

@PerActivity
abstract fun dialogUtils() : DialogUtils

为什么?不用了您已经可以注入 DialogUtils ,因为您已经用@PerActivity注释了类本身,并用@Inject注释了构造函数。 Dagger会在需要DialogUtils的地方自动进行所需的绑定。仅在注入抽象类型时才编写provide / bind方法。在这种情况下,DialogUtils没有实现您在Activity中注入的抽象类型。您可以直接注入实际的实现,因此无需设置任何绑定。

2。 HomeModuleBinds.kt

将“活动”绑定更改为更多您想要绑定到Activity的特定Activity,在本例中为MainActivity。然后,Dagger会在 DialogUtils 要求时将其绑定到Activity。您需要为要在Activity自己的模块中使用 DialogUtils 的每个Activity进行此操作-您将其作为参数传递给{{1} },在这种情况下为 HomeModuleBinds.kt

@ContributeAndroidInjector(modules = [...])

3。 DialogUtils

您当前定义方法@Binds @PerActivity abstract fun bindMainActivity(mainActivity: MainActivity): Activity 的方式将返回一个lambda!删除等于showDialog(String)

=

4。 MainActivity.kt

从注入的字段中删除范围注释。

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

}

您只能使用范围注释来注释组件,提供/绑定方法和类!