Wrong graph in Dagger 2 with kotlin - android

I am trying to use Dagger 2 with Kotlin and I am missing something. The problem comes when I try to inject an MVP presenter into the Fragment.
These are my files:
AppClass
class AppClass : Application(), HasActivityInjector {
#Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
override fun onCreate() {
super.onCreate()
DaggerAppComponent.builder()
.application(this)
.build()
.inject(this)
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
override fun activityInjector(): AndroidInjector<Activity> = dispatchingAndroidInjector
companion object {
lateinit var instance: AppClass private set
}
}
AppComponent
#Singleton
#Component(modules = [AndroidSupportInjectionModule::class,
AppModule::class,
ActivityBuilder::class])
interface AppComponent {
fun inject(appClass: AppClass)
#Component.Builder
interface Builder {
#BindsInstance
fun application(appClass: AppClass): Builder
fun build(): AppComponent
}
}
AppModule
#Module
class AppModule {
#Provides
#Singleton
fun provideContext(app : AppClass) = app
#Provides
#Singleton
fun provideDatabaseManager() = DatabaseManager()
}
ActivityBuilder
#Module
abstract class ActivityBuilder {
#ContributesAndroidInjector(modules = [ActivityModule::class, HomeFragmentProvider::class])
internal abstract fun bindHomeActivity(): HomeActivity
}
HomeFragmentProvider
#Module
public abstract class HomeFragmentProvider {
#ContributesAndroidInjector(modules = HomeFragmentModule.class)
abstract HomeFragment provideHomeFragmentFactory();
}
HomeFragmentModule
#Module
class HomeFragmentModule {
#Provides
fun provideHomePresenter(databaseManager: DatabaseManager): HomeContract.Presenter {
return HomePresenter(databaseManager)
}
}
HomeFragment
class HomeFragment : HomeContract.View {
#Inject lateinit var mPresenter: HomeContract.Presenter
override fun onCreate(savedInstanceState: Bundle?) {
AndroidSupportInjection.inject(this)
super.onCreate(savedInstanceState)
if (arguments != null) {
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)
return view
}
companion object {
private val STARTING_PAGE_INDEX = 0
fun newInstance(): HomeFragment {
val fragment = HomeFragment()
val args = Bundle()
fragment.arguments = args
return fragment
}
}
}
Log
...app/build/tmp/kapt3/stubs/debug/.../di/component/FragmentComponent.java:9: error: [Dagger/MissingBinding] ....HomeContract.Presenter cannot be provided without an #Provides-annotated method.
I try to inject the DatabaseManager in the Activity and works fine so I suppose that my problem is related to the Fragment dependencies.
Any help is appreciated.
UPDATE
HomePresenter
class HomePresenter() :
BasePresenter<HomeContract.View>(), HomeContract.Presenter {
private lateinit var mDatabaseManager : DatabaseManager
#Inject constructor(databaseManager: DatabaseManager) : this() {
this.mDatabaseManager = databaseManager
}
}

Define HomePresenter variable as a function parameter, as below:
#Module
class HomeFragmentModule {
#Provides
fun provideHomePresenter(homePresenter: HomePresenter): HomeContract.Presenter {
return homePresenter
}
}
Modify your HomePresenter class as below:
class HomePresenter #Inject constructor(val databaseManager: DatabaseManager) :
BasePresenter<HomeContract.View>(), HomeContract.Presenter {
....
}
Also, you can use DatabaseManager instance from the constructor directly by marking it as val, there is no need to define it separately.
In AppComponent, try using AndroidInjectionModule::class if you are not using support Fragments.
#Singleton
#Component(modules = [AndroidInjectionModule::class,
AppModule::class,
ActivityBuilder::class])
interface AppComponent {
....
}
Hope this will resolve your issue!

I came up with the problem. If I change the injection in the HomeFragment from #Inject lateinit var mPresenter: HomeContract.Presenter to #Inject lateinit var mPresenter: HomePresenter everything works fine.

Related

how to inject viewModel into a fragment - dagger 2

Hi I am using dagger 2 for dependency injection and when I try to inject MainActivityViewModel in my fragment I get the error lateinit property viewModelx has not been initialized
these are the related dependency files and Fragment
RetroModule
#Module
class RetroModule {
#Singleton
#Provides
fun getRetrofitInstance(): Retrofit {
return Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
#Singleton
#Provides
fun getApiService(): ApiServiceInterface =
getRetrofitInstance().create(ApiServiceInterface::class.java)
companion object {
private val baseURL = "https://android-interview.s3.eu-west-2.amazonaws.com/"
}
}
RetroComponent
#Singleton
#Component(modules = [RetroModule::class])
interface RetroComponent {
fun inject(mainActivityViewModel: MainActivityViewModel)
}
Fragment
class CreditScoreFragment : Fragment() {
#Inject lateinit var viewModelx: MainActivityViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCreditScoreBinding.inflate(inflater, container, false)
val view = binding.root
initViewModel()
initView()
return view
}
private fun initViewModel() {
viewModelx.getCreditReportObserver().observe(viewLifecycleOwner, Observer<CreditReport> {
showScoreUI(true)
binding.score.text = it.creditReportInfo.score.toString()
binding.maxScoreValue.text = "out of ${it.creditReportInfo.maxScoreValue}"
initDonutView(
it.creditReportInfo.score.toFloat(),
it.creditReportInfo.maxScoreValue.toFloat()
)
})
viewModelx.getServerErrorLiveDataObserver().observe(viewLifecycleOwner, Observer<Boolean> {
if(it) {
showScoreUI(false)
showToastMessage()
}
})
viewModelx.getCreditReport()
}
companion object {
#JvmStatic
fun newInstance() =
CreditScoreFragment().apply {}
}
}
Error update
xxx/app/build/tmp/kapt3/stubs/debug/com/example/clearscore/di/ViewModelModule.java:18: error: #Binds methods' parameter type must be assignable to the return type
public abstract androidx.lifecycle.ViewModelProvider.Factory bindMainActivityViewModel_Factory(#org.jetbrains.annotations.NotNull()
^xxx/app/build/tmp/kapt3/stubs/debug/com/example/clearscore/di/RetroComponent.java:18: error: #Component.Factory abstract methods must return the #Component type or a supertype of the #Component. Inherited method: create(T)
public static abstract class Factory implements dagger.android.AndroidInjector.Factory<com.example.clearscore.MyApplication> {
^xxxapp/build/tmp/kapt3/stubs/debug/com/example/clearscore/di/RetroComponent.java:6: error: com.example.clearscore.di.ViewModelModule has errors
#dagger.Component(modules = {com.example.clearscore.di.RetroModule.class, com.example.clearscore.di.ViewModelModule.class})
ViewModelModule
#Module
abstract class ViewModelModule {
#Binds
#IntoMap
#ViewModelKey(MainActivityViewModel::class )
// Bind your View Model here
abstract fun bindMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel
#Binds
// Bind viewModelFactory if you have custom ViewModelFactory
abstract fun bindMainActivityViewModel_Factory(factory: MainActivityViewModel_Factory): ViewModelProvider.Factory
}
MainActivityViewModel_Factory
#DaggerGenerated
#SuppressWarnings({
"unchecked",
"rawtypes"
})
public final class MainActivityViewModel_Factory implements Factory<MainActivityViewModel> {
private final Provider<DataRepository> dataRepositoryProvider;
public MainActivityViewModel_Factory(Provider<DataRepository> dataRepositoryProvider) {
this.dataRepositoryProvider = dataRepositoryProvider;
}
#Override
public MainActivityViewModel get() {
return newInstance(dataRepositoryProvider.get());
}
public static MainActivityViewModel_Factory create(
Provider<DataRepository> dataRepositoryProvider) {
return new MainActivityViewModel_Factory(dataRepositoryProvider);
}
public static MainActivityViewModel newInstance(DataRepository dataRepository) {
return new MainActivityViewModel(dataRepository);
}
}
You need to declare the provider in your viewmodel module:
#Binds
#IntoMap
#ViewModelKey(MainActivityViewModel::class)
abstract fun provideMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel
Your Fragment must be declared in your module too:
#FragmentScope
#ContributesAndroidInjector
abstract fun provideCreditScoreFragment(): CreditScoreFragment
And in your fragment, when you declare the viewmodel, is necessary to init it, for example with a lazy initialization, as you wish:
private val viewModel: MainActivityViewModel by lazy {
ViewModelProvider(this, yourViewModelFactory).get(MainActivityViewModel::class.java)
}
And finally you can inject your viewmodel factory in the fragment (remember to declare the factory in the module)
I think you are missing onething. Add AndroidSupportInjection.inject(this) in onAttach or onCreate based on when u start using your dependency this will help dagger to inject.

lateinit property ViewModelFactory has not been initialized

I'm using dagger 2.25.2 and androidx.lifecycle for dependency injection in my android project. But I've got error ViewModelFactory has not been initialized
Here is my code's
class PropertyActivity : AppCompatActivity() {
#Inject
lateinit var propertyViewModelFactory: PropertyViewModelFactory
lateinit var propertyViewModel: PropertyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.property_activity)
propertyViewModel = ViewModelProviders.of(this, propertyViewModelFactory).get(
PropertyViewModel::class.java)
propertyViewModel.loadProperties()
}
ViewModelFactory:
class PropertyViewModelFactory #Inject constructor(
private val propertyViewModel: PropertyViewModel) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(PropertyViewModel::class.java!!)) {
return propertyViewModel as T
}
throw IllegalArgumentException("Unknown class name")
}
}
AppModule:
#Module
class AppModule(val app: Application){
#Provides
#Singleton
fun provideApplication(): Application = app
#Provides
#Singleton
fun providePropertyViewModelFactory(factory: PropertyViewModelFactory): ViewModelProvider.Factory = factory
}
BuildersModule:
#Module
abstract class BuildersModule {
#ContributesAndroidInjector
abstract fun contributePropertyActivity(): PropertyActivity
}
AppComponent:
#Singleton
#Component(modules = arrayOf(AndroidInjectionModule::class,BuildersModule::class, AppModule::class))interface PlotComponent {
fun inject(app: Application)
}
Application Class :
class PlotApplication : Application(), HasAndroidInjector {
#Inject
lateinit var activityInjector: DispatchingAndroidInjector<Any>
override fun onCreate() {
super.onCreate()
DaggerPlotComponent.builder()
.appModule(AppModule(this))
.build().inject(this)
}
override fun androidInjector(): AndroidInjector<Any> = activityInjector
}
I doesn't see where you inject dependency in your activity. The problem may be in this.
Add
AndroidInjection.inject(this)
in your onCreate

How to use pass the activity to an dagger module using the new `dagger-android`

Android Studio 3.4
dagger-android 2.21
How to use pass the activity to an dagger module using the new dagger-android
Before using the older version of dagger we could pass the Activity in the constructor and return that in the provider method. But I not sure how to do that with dagger-android
I have the following module. However, dagger doesn't now about the ForecastActivity.
#Module
class ActivityModule {
#Reusable
#Provides
fun provideRetryListener(forecastActivity: ForecastActivity): RetryListener {
return forecastActivity
}
}
The RetryListener is a interface that the ForecastActivity implements. I want to be able to inject this RetryListener into my RetryFragment i.e.
class RetryFragment : Fragment() {
#Inject
lateinit var retryListener: RetryListener // Inject here
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
AndroidSupportInjection.inject(this)
super.onCreateView(inflater, container, savedInstanceState)
retryListener.onRetry() // usage like this
return inflater.inflate(R.layout.failurecase_layout, container, false)
}
}
In the forecastActivity
class ForecastActivity : AppCompatActivity(), RetryListener {
#Inject
lateinit var forecastPresenter: ForecastPresenter
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
}
override fun onRetry() {
/* do something here */
}
}
My ActivityBuilder is the following:
#Module
abstract class ActivityBuilder {
#ContributesAndroidInjector(modules = [ActivityModule::class])
abstract fun injectIntoRetryFragment(): RetryFragment
}
My component is this:
#Singleton
#Component(modules = [
AndroidSupportInjectionModule::class,
ActivityBuilder::class,
ActivityModule::class])
interface StockComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: StockApplication): Builder
fun build(): StockComponent
}
fun inject(application: StockApplication)
}
And my Application is:
class StockApplication : Application(), HasActivityInjector, HasSupportFragmentInjector {
#Inject
lateinit var dispatchingAndroidActivityInjector: DispatchingAndroidInjector<Activity>
#Inject
lateinit var dispatchingAndroidFragmentInjector: DispatchingAndroidInjector<Fragment>
override fun onCreate() {
super.onCreate()
DaggerStockComponent
.builder()
.application(this)
.build()
.inject(this)
}
override fun activityInjector(): AndroidInjector<Activity> {
return dispatchingAndroidActivityInjector
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
return dispatchingAndroidFragmentInjector
}
}
So the question is when using dagger-android how can I inject the RetryListener into the RetryFragment that the RetryListener is implemented by the ForecastActivity?
Many thanks in advance
I can't see a module that provides your ForecastActivity, i.e.:
#ContributesAndroidInjector
abstract fun forecastActivity(): ForecastActivity
The Activity will need to implement HasSupportFragmentInjector, and supply a DispatchingAndroidInjector<Fragment>

lateinit property dispatchingAndroidInjector has not been initialized

I receive the above error "lateinit property dispatchingAndroidInjector has not been initialized " when I run my fragment in dagger2 .
The above error is triggered in my application class which is below
KotlinTemplateApplication.kt
class KotlinTemplateApplication:Application(), HasActivityInjector {
lateinit var retroComponent:RetroComponent
#Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
companion object {
#get:Synchronized
lateinit var instance: KotlinTemplateApplication
private set
}
override fun onCreate() {
super.onCreate()
instance = this
retroComponent = DaggerRetroComponent.builder().retroModule(RetroModule(APIURL.BASE_URL)).build()
//retroComponent.inject()
}
fun fetchRetroComponent():RetroComponent{
return retroComponent
}
override fun activityInjector(): AndroidInjector<Activity> {
return dispatchingAndroidInjector
}
}
My Fragment class is as below :
I called dagger related code in onAttach() method of fragment :
RetroDIFragment:
class RetroDIFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
lateinit var retroDIListViewModel: RetroDIListViewModel
lateinit var retroFitDIView: View
#Inject
lateinit var apiService: APIService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
retroDIListViewModel = ViewModelProviders.of(activity!!).get(RetroDIListViewModel::class.java)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
retroFitDIView = inflater.inflate(R.layout.fragment_retro_di, container, false)
return retroFitDIView
}
override fun onAttach(context: Context?) {
super.onAttach(context)
AndroidInjection.inject(activity)
KotlinTemplateApplication.instance.fetchRetroComponent().inject(this#RetroDIFragment)
retroDIListViewModel.fetchPostsFromWebSevice(apiService).observe(this,object : Observer<List<RetroModel>>{
override fun onChanged(t: List<RetroModel>?) {
for (i in t!!.indices)
println(t[i].id)
}
})
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment RetroDIFragment.
*/
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String, param2: String) =
RetroDIFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
My component is as below :
RetroComponent :
#Singleton
#Component(modules = arrayOf(RetroModule::class))
interface RetroComponent {
fun inject(retroDIFragment: RetroDIFragment)
}
My Module is as below:
#Module
public class RetroModule(var urlPath:String) {
init{
this.urlPath = urlPath
}
#Singleton
#Provides
fun provideServiceAPI(retrofit: Retrofit):APIService{
return retrofit.create(APIService::class.java)
}
#Singleton
#Provides
fun provideRetrofit():Retrofit{
val retrofit = Retrofit.Builder()
.baseUrl(urlPath)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(providesOkHttpClientBuilder())
.build()
return retrofit
}
private fun providesOkHttpClientBuilder(): OkHttpClient {
val httpClient = OkHttpClient.Builder()
return httpClient.readTimeout(1200, TimeUnit.SECONDS)
.connectTimeout(1200, TimeUnit.SECONDS).build()
}
}
My Activity is as below
class RetroFitActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_retro_fit)
supportFragmentManager.beginTransaction().replace(R.id.container_retro_di, RetroDIFragment()).commit()
}
}
I included below code in my Gradle:
implementation 'com.google.dagger:dagger:2.19'
implementation 'com.google.dagger:dagger-android:2.19'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.19'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
kapt 'com.google.dagger:dagger-android-processor:2.19'
kapt 'com.google.dagger:dagger-compiler:2.19'
//moxy
compile 'com.arello-mobile:moxy-app-compat:1.1.1'
kapt 'com.arello-mobile:moxy-compiler:1.1.1'
Can anyone help me in fixing this issue.
You need to change the AppComponent class inject method parameter:
#Singleton
#Component(modules = [
AndroidInjectionModule::class,
ActivityModule::class,
AppModule::class
])
interface AppComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(app: Application) // This is the piece of code you need to change
}
#Singleton
#Component(modules = [
AndroidInjectionModule::class,
ActivityModule::class,
AppModule::class
])
interface AppComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(app: YourCustomAppClass) // Change to your custom app class
}
Also, where you are doing this
DaggerAppComponent
.builder()
.application(yourAppInstance)
.build()
.inject(yourAppInstance)
yourAppInstance needs to be of type YourCustomApp class instead of Application.
The dispatchingAndroidInjector property has to be set eventually.
#Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
As it's annotated with #Inject, it seems like you wanted to inject it. But since KotlinTemplateApplication is an Application, you need to do this manually on your component:
retroComponent.inject(this#KotlinTemplateApplication)
To use Dagger in a Fragment, you must add a DispatchingAndroidInjector <Fragment> in KotlinTemplateApplication
Edit KotlinTemplateApplication
class KotlinTemplateApplication : Application() , HasActivityInjector, HasSupportFragmentInjector {
#Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity>
#Inject lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>
override fun onCreate() {
super.onCreate()
........
DaggerAppComponent.builder().application(this).build().inject(this)
.........
}
override fun activityInjector(): AndroidInjector<Activity> = activityInjector
override fun supportFragmentInjector(): AndroidInjector<Fragment> = fragmentInjector
}
You can also create a special module for Fragments and then add it to interface RetroComponent
#Component(modules = arrayOf(RetroModule::class,FragmentModule::class)
#Module
abstract class FragmentModule {
#ContributesAndroidInjector
internal abstract fun contributeRetroDIFragment(): RetroDIFragment
}
Then in your Fragment RetroDIFragment
class RetroDIFragment : Fragment() {
......
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
retroFitDIView = inflater.inflate(R.layout.fragment_retro_di, container, false)
return retroFitDIView
}
.........
/*---------------- Dagger Injection for Fragment -------------*/
#Override
override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this)
super.onAttach(context);
}
}
this might be too late but this worked for me...
#set:Inject
internal var activityDispatchingAndroidInjector:DispatchingAndroidInjector<Activity>? = null
remove lateinit and use internal with #set:Inject instead of #Inject
this worked like charm for me.
I had the same issues with Dagger2.26v,
to fix ,
make sure ApplicationComponent extends AndroidInjector<SampleApplication> like
this:
#Singleton
#Component(modules = AndroidInjectionModule::class)
interface ApplicationComponent : AndroidInjector<SampleApplication> { …}

Dagger 2.11 - how to make Activity and Fragment share common values?

I am currently learning Dagger 2 on Android and I would like to inject the Activity's injection into the Fragment, but I do not know how.
This a working setup, that shows the values being injected into the fragment and the activity.
Sorry for the wall of code, I simplified my code so that it only contains the relevant parts.
#Singleton
#Component(modules = arrayOf(AndroidSupportInjectionModule::class, AppModule::class, BuildersModule::class))
interface AppComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun setApplication(application: Application): Builder
fun build(): AppComponent
}
fun apiService() : ApiService
fun inject(app: App)
}
#Module(subcomponents = arrayOf(MainActivitySubComponent::class, MainFragmentSubComponent::class))
class AppModule
#Module
abstract class BuildersModule {
#Binds
#IntoMap
#ActivityKey(MainActivity::class)
abstract fun bindMainActivity(builder: MainActivitySubComponent.Builder): AndroidInjector.Factory<out Activity>
#Binds
#IntoMap
#dagger.android.support.FragmentKey(MainFragment::class)
abstract fun bindMainFragment(builder: MainFragmentSubComponent.Builder): AndroidInjector.Factory<out Fragment>
}
The AppComponent is created inside the Application:
class App : Application(), HasActivityInjector {
#Inject
var activityInjector: DispatchingAndroidInjector<Activity>? = null
override fun onCreate() {
super.onCreate()
DaggerAppComponent
.builder()
.setApplication(this)
.build()
.inject(this)
}
override fun activityInjector(): AndroidInjector<Activity>? {
return activityInjector
}
}
MainActivity:
#Subcomponent(modules = arrayOf(MainActivityModule::class))
interface MainActivitySubComponent : AndroidInjector<MainActivity> {
#Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainActivity>()
}
#Module
class MainActivityModule {
#Provides
fun providePresenter(mainView: MainView, apiService: ApiService): MainPresenter
= MainPresenterImpl(mainView, apiService)
}
class MainActivity : AppCompatActivity(), HasSupportFragmentInjector {
#Inject
lateinit var mainPresenter: MainPresenter
#Inject
lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.add(R.id.container, MainFragment())
.commitAllowingStateLoss()
}
}
override fun supportFragmentInjector() = fragmentInjector
}
MainFragment:
#Subcomponent(modules = arrayOf(MainFragmentModule::class))
interface MainFragmentSubComponent : AndroidInjector<MainFragment> {
#Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainFragment>()
}
#Module
class MainFragmentModule {
#Provides
fun providePresenter(mainView: MainView, apiService: ApiService): MainPresenter
= MainPresenterImpl(mainView, apiService)
}
class MainFragment : Fragment() {
#Inject
lateinit var mainPresenter: MainPresenter
override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
}
}
So I've found out how activity and fragment can use the same ApiService class.
I'd like to inject the same instance of MainPresenter in both MainActivity and MainFragment.
How could I gain access to the Activity's injected MainPresenter without changing the code in MainFragment? Basically, I don't want the MainFragment to know anything about how it is injected.

Categories

Resources