I'm using the new dagger.android
package from Dagger 2 to inject Android dependencies in my project.
BaseActivity
In my BaseActivity
I have member variables to be injected. This way:
abstract class BaseActivity : AppCompatActivity() {
@Inject
lateinit var prefs: MyPreferenceDataStore
...// more @Injected members
}
I do it because I want subclasses of BaseActiviy
can have access to injected members of BaseActivity
:
class SubClassActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle) {
val x = prefs.getXXX //use prefs variable from parent class
}
}
This is my ApplicationComponent:
@Singleton @Component(modules = arrayOf(
ApplicationModule::class,
ActivityBindingModule::class,
AndroidSupportInjectionModule::class
))
interface ApplicationComponent {
@Component.Builder interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): ApplicationComponent
}
fun inject(app: AndroidApplication)
}
The ApplicationModule
class has simple @Provides
annotated methods:
@Module
class ApplicationModule {
@Singleton @Provides
fun providesMyPreferenceDataStore(context: Context): MyPreferenceDataStore {
return MyPreferenceDataStoreImpl(context)
}
// more @Provides annotated methods
}
I think the problem is in my ActivityBindingModule
@Module
abstract class ActivityBindingModule {
@PerActivity
@ContributesAndroidInjector(
modules = arrayOf(BaseActivityModule::class
))
abstract fun bindBaseActivity(): BaseActivity
@PerActivity
@ContributesAndroidInjector(
modules = arrayOf(
BaseActivityModule::class
))
abstract fun bindSubClassActivity(): SubClassActivity
}
This is what I have tried so far:
Make the bindSubClassActivity()
method not to depend of BaseActivityModule::class
, didn't work.
Move the providesMyPreferenceDataStore
from ApplicationModule
to the BaseActivityModule
, so that the class is:
@Module
class BaseActivityModule {
@PerActivity @Provides
fun providesMyPreferenceDataStore(context: Context): MyPreferenceDataStore {
return MyPreferenceDataStoreImpl(context)
}
}
And this is the error I'm getting:
Error: [dagger.android.AndroidInjector.inject(T)] com.example.BaseActivity cannot
be provided without an @Provides-annotated method.
This type supports members injection but cannot
be implicitly provided.
First, an abstract class isn't component-scanned since it can't be instantiated without a concrete subclass. Second, setter injection is possible in an abstract class, but it's risky if we don't use the final keyword for the setter method. The application may not be stable if a subclass overrides the setter method.
onCreate() , an activity attaches fragments that might want to access activity bindings. When using fragments, inject Dagger in the fragment's onAttach() method. In this case, it can be done before or after calling super. onAttach() .
inject. Inject annotation to identify which constructors and fields it is interested in. Use @Inject to annotate the constructor that Dagger should use to create instances of a class. When a new instance is requested, Dagger will obtain the required parameters values and invoke this constructor.
I didn't understand exactly what you try to do but this solutions based in what i understand
AppComponent should look like this
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
ActivityModule::class])
interface AppComponent : AndroidInjector<DaggerApplication> {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
}
your base activity which will inject all the objects
abstract class BaseActivity : DaggerAppCompatActivity() {
@Inject
lateinit var prefs: SharedPreferences
//other objects to inject
}
The activity that will inherit from it eg:MainActivity
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
prefs.getBoolean("s", true)
}
}
And Activity module
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity
@ContributesAndroidInjector
abstract fun bindBaseActivity():BaseActivity
}
AppModule
@Module
class AppModule {
@Singleton
@Provides
fun providesMyPreferenceDataStore(application: Application): SharedPreferences {
return application.getSharedPreferences("test", Context.MODE_PRIVATE)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With