0
votes

I am trying to use Dagger 2 in Android. Implementation is very straightforward. Below are dagger 2 related Components and Modules:

ApplicationComponent.kt

@Singleton
@Component(modules = arrayOf(AppModule::class))
interface ApplicationComponent {
    fun inject(app: Application)
    fun inject(mainActivity: MainActivity)
    fun plusMainAcitvityComponent(mainActivityModule: MainActivityModule): MainActivityComponent
}

MainActivityComponent.kt

@Subcomponent(modules = arrayOf(MainActivityModule::class, GoogleApiClientModule::class))
interface MainActivityComponent{

    fun inject(mainActivity: MainActivity)

}

AppModule.kt

@Module
class AppModule(val app: Application){

    @ApplicationContext
    @Provides
    fun providesApplicationContext() = app

}

GoogleApiClientModule.kt

@Module
class GoogleApiClientModule{

    companion object {
        val TAG = "GoogleApiClientModule"
    }

    @Singleton
    @Provides
    fun providesGoogleApiClient(@ActivityContext activity: MainActivity, connectionFailedListener: OnConnectionFailedListener) =
            GoogleApiClient.Builder(activity)
                    .addApi(Places.GEO_DATA_API)
                    .addApi(Places.PLACE_DETECTION_API)
                    .enableAutoManage(activity, connectionFailedListener)
                    .build()

    @Singleton
    @Provides
    fun providesConnectionFailedListener() = OnConnectionFailedListener {
        Log.d(TAG, "GAC connection has failed")
    }

}

GooglePlacesClientModule.kt

@Module
class GooglePlacesClientModule {

    @Provides
    fun providesGeoDataClient(@ActivityContext activity: MainActivity) = Places.getGeoDataClient(activity, null)

}

MainActivityModule.kt

@Module
class MainActivityModule(val activity: MainActivity){

    @ActivityContext
    @Provides
    fun providesActivityContext() = activity


}

Below is my Main Activity where I am injecting the above components:

 class MainActivity : AppCompatActivity(), OnMapReadyCallback {

    lateinit var binding: ActivityMainBinding
    lateinit var mapFragment: SupportMapFragment
    @Inject lateinit var app: App
    @Inject lateinit var mainViewModelFactory: MainViewModelFactory
    lateinit var mainViewModel: MainViewModel


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //Data binding
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        //Dagger inject
        App.appComponent.inject(this)
        app.plustMainAcitvityComponent(this)?.inject(this)
        //Viewmodel init
        mainViewModel = ViewModelProviders.of(this, mainViewModelFactory).get(MainViewModel::class.java)
        //Ui init
        setSupportActionBar(binding.toolbarLayout?.toolbar)
        setupBottomSheetLayout()
        setupGoogleMap()
    }
      ----
     ---
   }

Below is my App where Dagger is initialized:

class App: Application(){

    var mainActivityComponent: MainActivityComponent? = null

    companion object {
        lateinit var appComponent: ApplicationComponent
    }

    override fun onCreate() {
        super.onCreate()
        setupDagger()
    }

    fun setupDagger(){
        appComponent = DaggerApplicationComponent.builder().appModule(AppModule(this)).build()
    }


    fun plustMainAcitvityComponent(activity: MainActivity) : MainActivityComponent?{
        if(mainActivityComponent == null) {
            mainActivityComponent = appComponent.plusMainAcitvityComponent(MainActivityModule(activity))
        }
        return mainActivityComponent
    }

    fun clearMainActivityComponent(){
        mainActivityComponent = null
    }

}

When I run the app I am getting a internal compiler error. Below are my IDE logs:

2017-11-29 11:54:39,953 [J pool 2/4] WARN - hes.resolve.KotlinCacheService - Could not find correct module information. Reason: Analyzing element of type class com.android.tools.idea.databinding.LightGeneratedComponentClass with no containing file Text: null 2017-11-29 11:54:39,953 [J pool 2/4] WARN - .resolve.jvm.JvmAnalyzerFacade - Java referenced null from LibraryInfo(libraryName=com.android.databinding:library-1.3.1) Referenced class was: JavaClassImpl: DATA binding component class

NOTE: MainActivityComponent is a SubComponent of ApplicationComponent. Even though ApplicationComponent has only one module at present, Further modules will be added in the future

2

2 Answers

0
votes

I can't really understand the error message as of now. There are two things that I can see which can make it go wrong here
1) To add a subcomponent to a parent component, add the subcomponent class to the subcomponents attribute of a @Module that the parent component installs. Then the subcomponent’s builder can be requested from within the parent

@Module(subcomponents = XYZ.class) class AppModule(val app: Application){

2) Also, you are providing the same scope to subcomponent and component which is not allowed unless there is no ambiguity in resolution. Please read the documentation here at https://google.github.io/dagger/subcomponents.html

-1
votes

Your error has nothing to do with Dagger, but with Android's data binding library. Are you using that? If not, remove it from your dependencies and try again?