I have created a small sample to test dagger2 implementation. I have created a utility class in which an Activity's instance is to be injected. Is there any way to get this utility class instance in Activity itself using dagger2
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()
}
}
Is there any way I can use DialogUtils instance in MainActivity Using dagger2 dependency cycle?
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
Don't inject the Activity into the Utility class.
Then in your Activity call:
dialogUtils.showDialog( "hello", MyACtivity.this)
In 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?
Yes, there is. To do that, you'll have to do the following changes in your Dagger setup:
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
. Dagger will automagically do the required binding wherever DialogUtils
is needed. You write provide/bind methods only when you're injecting an abstract type. In this case, DialogUtils
is not implementing an abstract type that you inject in the Activity
. You inject the actual implementation directly so you don't need to setup any bindings.
2. HomeModuleBinds.kt
Change the Activity binding to more the specific Activity
you want to bind to Activity
, in this case it's MainActivity
. Dagger will then understand that it needs to bind it to Activity
when DialogUtils asks for it. 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 .
@Binds
@PerActivity
abstract fun bindMainActivity(mainActivity: MainActivity): Activity
3. DialogUtils
The way you have method showDialog(String)
defined currently, it returns a lambda! Remove the equals =
.
fun showDialog(error: String) {
val alertDialogBuilder = AlertDialog.Builder(activity)
alertDialogBuilder.setTitle(error).create().show()
}
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!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.