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