dagger 2 Subcomponent - android

while Dagger implementation i have below error. please help me resolve it.
dagger/component/AppComponent.java:10: error: [com.example.testproject.app.dagger.component.PostLoginComponent.inject(com.example.testproject.view.photo.PhotoListActivity)] com.example.testproject.data.UserStore cannot be provided without an #Inject constructor or from an #Provides-annotated method.
My understanding - I have created AppComponent and AppModule which is parent for PostLoginComponent and PostLoginModule (as they are subcomponent).
photoListViewModel is injected in PhotoListActivity. photoListViewModel is provide by postLoginComponent and PostLoginModule.Now photoListViewModel need UserStore as dependency which is present in AppModule.
So as per my understanding all object from parent module are available for child module.
in this case UserStore from AppModule should be available for PhotoListViewModel in PostLoginModule.
But as per error UserStore is not provided.
#Module
abstract class AppModule {
#Module
companion object {
#Provides
fun provideUserStore(context: Context): UserStore {
return UserStore(context)
}
}
}
#Component(modules = [AppModule::class])
interface AppComponent {
fun postLoginComponent(): PostLoginComponent.Builder
#Component.Builder
interface Builder {
#BindsInstance
fun bindData(context: Context): Builder
fun build(): AppComponent
}
}
#Module
abstract class PostLoginModule {
#Binds
#IntoMap
#ViewModelKey(PhotoListViewModel::class)
abstract fun bindViewModel(viewModel: PhotoListViewModel): ViewModel
#MustBeDocumented
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.RUNTIME)
#MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
}
#Subcomponent(modules = [PostLoginModule::class])
interface PostLoginComponent {
fun inject(activity: PhotoListActivity)
#Subcomponent.Builder
interface Builder {
fun build(): PostLoginComponent
}
}
class PhotoListActivity() : PostLoginActivity() {
var adapter = PhotoListAdapter(
mutableListOf(
PhotoItem("", "akash"),
PhotoItem("", "akash"),
PhotoItem("", "akash"),
PhotoItem("", "akash")
)
)
#Inject
lateinit var factory: ViewModelFactory
private val photoListViewModel: PhotoListViewModel by lazy {
ViewModelProvider(this, factory).get(PhotoListViewModel::class.java)
}
override fun setLayoutId(): Int? {
return R.layout.activity_photo_list
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
TestApp.get(this).appComponent().postLoginComponent().build().inject(this)
initView()
}
private fun initView() {
textView.setOnClickListener {
adapter.clearData()
}
rvPhotoList.initRecyclerView {
it.layoutManager = LinearLayoutManager(this)
it.adapter = adapter
}
adapter.setItemClickListener(OnRecyclerViewOnItemClickListener { parent, view, position -> })
rvPhotoList.addErrorView(EmptyErrorView(this))
getPhotoList()
}
private fun getPhotoList() {
adapter.addItems(photoListViewModel.getPhotoList())
}
}
class PhotoListViewModel #Inject constructor(userStore: UserStore) : BaseViewModel() {
fun getPhotoList(): List<PhotoItem> {
return mutableListOf(
PhotoItem("", "aher"),
PhotoItem("", "aher"),
PhotoItem("", "aher"),
PhotoItem("", "aher")
)
}
}

Related

Hilt particular feature dependency

#Module(includes = [AuthModule.ViewModel::class, AuthModule.UseCase::class, AuthModule.Api::class, AuthModule.Repository::class, AuthModule.Interactor::class])
#InstallIn(ActivityComponent::class)
class AuthModule {
#Module
#InstallIn(ActivityComponent::class)
class ViewModel() {
#Provides
fun providesRegisterViewModel(activity:FragmentActivity): RegisterViewModel {
val registerViewModel = ViewModelProvider(activity).get(RegisterViewModel::class.java)
return registerViewModel
}
}
#Module
#InstallIn(ActivityComponent::class)
class UseCase {
#Provides
fun providesRegisterationUseCase(registrationApi: RegistrationApi, userRepository: UserRepository): RegistrationUsecase {
val registrationUsecase = RegistrationUsecase(registrationApi, userRepository)
return registrationUsecase
}
}
#Module
#InstallIn(ActivityComponent::class)
class Api {
#Provides
fun provideRegistrationApi(retrofit: Retrofit): RegistrationApi {
val registrationService = retrofit.create(RegistrationService::class.java)
return RegistrationApi(registrationService)
}
}
#Module
#InstallIn(ActivityComponent::class)
class Repository {
#Provides
fun provideUserRepository(realm: Realm): UserRepository = UserRepository(realm)
}
#Module
#InstallIn(ActivityComponent::class)
class Interactor {
#Provides
fun provideSignInInteractor(registerViewModel: RegisterViewModel): SignInInteractor = SignInInteractor(registerViewModel)
}
}
#Component(modules = [AuthModule::class])
interface AuthComponent {
fun inject(signInFragment: SignInFragment)
#Component.Builder
interface Builder {
fun activity(#BindsInstance fragmentActivity: FragmentActivity): Builder
fun build(): AuthComponent
}
}
class SignInFragment : Fragment() {
#Inject lateinit var signInInteractor:SignInInteractor
private lateinit var fragmentSignInBinding: FragmentSignInBinding
override fun onCreate(savedInstanceState: Bundle?) {
DaggerAuthModuleComponent.builder()
.activity(requireActivity()).build().inject(this)
super.onCreate(savedInstanceState)
}
i was trying to inject it in other fragments but it does not work. my aim is to make feature wise component so that only these fragment related to particular feature gets the dependency.
Hilt requires every module to use install annotation if i want hilt to install to my custom component is it possible.

How do add a Repository to the Dagger Room Module?

How do I add a Repository to the Dagger Room Module? My Repository uses application when I try to add this class to a Module I get an error. How do I properly embed this repository in Dagger so that later I can do an injection in my ViewModel class? Why the first two functions are normally implemented in the Room Module and the last one is not. Any help
My Repository:
class ContactRepository (application: Application) {
private var contactDao: ContactDao
private var allContacts: MutableLiveData<ArrayList<Contact>>
companion object {
#Volatile
private var INSTANCE: ContactRepository? = null
fun getInstance(application: Application): ContactRepository {
return INSTANCE ?: getInstance(application)
}
}
init {
val database: ContactDatabase? = ContactDatabase.getInstance(application.applicationContext)
contactDao = database!!.contactDao()
allContacts = contactDao.getAllContact()
}
fun insert(contact: Contact) {
InsertContactAsyncTask().execute(contact)
}
fun updateAll(contactsModel: List<ContactsModel>) {
}
fun update(contact: Contact) {
}
fun delete(contact: Contact) {
}
fun getAllContact(): MutableLiveData<ArrayList<Contact>> {
return allContacts
}
class InsertContactAsyncTask : AsyncTask<Contact, Unit, Unit>() {
private val contactDao: ContactDao? = null
override fun doInBackground(vararg param: Contact) {
contactDao?.insert(param[0])
}
}
}
RoomModule:
#Module
class RoomModule {
private lateinit var contactDatabase: ContactDatabase
fun RoomModule(application: Application) {
contactDatabase = Room.databaseBuilder<ContactDatabase>(application, ContactDatabase::class.java, "contact_database")
.build()
}
#Singleton
#Provides
fun providesRoomDatabase(): ContactDatabase {
return contactDatabase
}
#Singleton
#Provides
fun providesContactDao(contactDatabase: ContactDatabase): ContactDao {
return contactDatabase.contactDao()
}
#Provides
fun providesContactRepository(application: Application): ContactRepository {
return ContactRepository(application)
}
}
Exception:
public abstract interface ApplicationComponent {
^
android.app.Application is injected at com.infernal93.phonebookappmvvmanddagger.di.modules.RoomModule.providesContactRepository(application)
com.infernal93.phonebookappmvvmanddagger.room.ContactRepository is injected at
com.infernal93.phonebookappmvvmanddagger.viewmodels.ContactsViewModel(contactRepository)
com.infernal93.phonebookappmvvmanddagger.viewmodels.ContactsViewModel is injected at
com.infernal93.phonebookappmvvmanddagger.di.modules.ViewModelModule.bindViewModel(viewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.infernal93.phonebookappmvvmanddagger.viewmodels.ViewModelFactory(viewModelsMap)
AppComponent:
#Singleton
#Component(modules = [ContextModule::class, NetworkModule::class, RoomModule::class])
interface ApplicationComponent {
fun inject(activity: ContactListActivity)
fun inject(activity: AddContactActivity)
fun inject(app: Application)
}
ViewNodel:
class ContactsViewModel #Inject constructor(private val contactRepository: ContactRepository) : ViewModel() {
fun getAllContacts(): MutableLiveData<ArrayList<Contact>>{
val contacts = contactRepository.getAllContact()
return contacts
}
#Singleton
#Component(modules = [ContextModule::class, NetworkModule::class, RoomModule::class])
interface ApplicationComponent {
fun inject(app: App)
fun inject(activity: ContactListActivity)
fun inject(activity: AddContactActivity)
fun inject(viewModel: ContactsViewModel)
fun inject(apiRepository: ApiRepository)
// For fix Room compile bugs
fun contactDatabase(): ContactDatabase
fun contactDao(): ContactDao
fun contactRepository(): RoomRepository
}

Dagger 2 is throwing compiling error when coded with Kotlin

Dagger 2 is not able to create the subcomponent object when coded with kotlin.The same code is running fine when i am coding in java
// MainActivityComponent:
#Subcomponent
interface MainActivityComponent : AndroidInjector<MainActivity> {
#Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainActivity>() {
}
}
ActivityBindingModule:
#Module(subcomponents = [MainActivityComponent::class])
abstract class ActivityBindingModule {
#Binds
#IntoMap
#ActivityKey(MainActivity::class)
abstract fun getActivityInjectors(buider: MainActivityComponent.Builder): AndroidInjector.Factory<out Activity>
}
ActivityInjector:
class ActivityInjector #Inject constructor(val activityInjectors: Map<Class<out Activity>, Provider<AndroidInjector.Factory<out Activity>>>) {
val cache = HashMap<String, AndroidInjector<out Activity>>()
fun inject(activity: Activity) {
if (activity !is BaseActivity) {
throw IllegalArgumentException("activity must extend Base")
}
val instanceId = (activity as BaseActivity).getInstanceId()
if (cache.containsKey(instanceId)) {
val androidInjector = cache.get(instanceId) as AndroidInjector<Activity>
androidInjector.inject(activity)
} else {
val androidInjectorFactory =
activityInjectors.get(activity::class.java)?.get() as AndroidInjector.Factory<Activity>
val androidInjector = androidInjectorFactory.create(activity)
cache.put(instanceId, androidInjector)
androidInjector.inject(activity)
}
}
companion object {
fun get(context: Context): ActivityInjector {
return (context.applicationContext as MyApplication).getActivityInjectors()
}
}
}
MyApplication:
class MyApplication : Application() {
#Inject
lateinit var activityInjector: ActivityInjector
lateinit var applicationComponent: ApplicationComponent
override fun onCreate() {
super.onCreate()
applicationComponent = DaggerApplicationComponent.builder().applicaitonModule(ApplicaitonModule(this)).build()
applicationComponent.inject(this)
}
fun getActivityInjectors(): ActivityInjector {
return activityInjector
}
}
Error:
Expected:It should compile successfully and provide the proper
dependencies
Actual:: error: [Dagger/MissingBinding] java.util.Map,?
extends javax.inject.Provider>> cannot be provided without an
#Provides-annotated method.

Inject property into ViewModel using Dagger 2

I try to learn how to use Dagger 2. Please help with follow exception:
Exception:
UninitializedPropertyAccessException: lateinit property trips has not
been initialized
MainActivityViewModel:
class MainActivityViewModel : ViewModel() {
private lateinit var tripsLiveData: MutableLiveData<List<Trip>>
#Inject
lateinit var trips : List<Trip>
fun getTrips() : LiveData<List<Trip>> {
if (!::tripsLiveData.isInitialized){
tripsLiveData = MutableLiveData()
tripsLiveData.value = trips
}
return tripsLiveData
}
}
TripModule:
#Module
class TripModule{
#Provides
fun provideTrips(): List<Trip> {
var list = ArrayList<Trip>()
list.add(Trip(100,10))
list.add(Trip(200,20))
return list
}
}
AppComponent:
#Singleton
#Component(modules = [
AndroidSupportInjectionModule::class,
ActivityBuilder::class,
TripModule::class])
interface AppComponent{
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(app: MyApplication)
}
MainActivity:
class MainActivity : AppCompatActivity() {
#Inject
lateinit var tripsAdapter: TripsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
// Inject external dependencies
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupRecyclerView();
setUpViewModel();
}
private fun setupRecyclerView() {
recycler_view.apply {
layoutManager = LinearLayoutManager(context)
adapter = tripsAdapter
}
}
private fun setUpViewModel(){
val model = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
model.getTrips().observe(this, Observer { tripsAdapter.trips = it!! })
}
}
If you want your viewmodel's to be part of the dagger graph, you need to do several things - using dagger's multibindings (just once, for newer viewmodels it will be easier). You'd create new viewmodel factory which will take care of instantiating viewmodels. This factory will be part of dagger graph and therefore will have references to anything provided via dagger. You can then have either constructor injection via #Inject constructor(anyParameterFromDagger: Param) or #Inject lateinit var someParam: Param inside the body of viewmodel.
1) Create qualifier for view model classes
#MustBeDocumented
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.RUNTIME)
#MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
2) create viewmodel factory which takes values from dagger's multibindings
#Singleton
class DaggerViewModelFactory #Inject constructor(
private val creators: Map<Class<out ViewModel>, #JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
#Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) {
throw IllegalArgumentException("unknown model class $modelClass")
}
try {
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
3) have dagger module which will provide the factory (from point 2) and then your viewmodels
abstract class YourDaggerModuleWhichThenNeedToBePartOfYourGraphAsIncluded {
#Binds
abstract fun bindViewModelFactory(factory: DaggerViewModelFactory): ViewModelProvider.Factory // this needs to be only one for whole app (therefore marked as `#Singleton`)
#Binds
#IntoMap
#ViewModelKey(MainActivityViewModel::class)
abstract fun bindMainActivityViewModel(vm: MainActivityViewModel): ViewModel // for every viewmodel you have in your app, you need to bind them to dagger
}
4) in your activity, when you get your viewmodel, you need to use the factory from dagger: (places changed marked as // TODO in the code below)
class MainActivity : AppCompatActivity() {
#Inject
lateinit var tripsAdapter: TripsAdapter
#Inject
lateinit var viewModelFactory: ViewModelProvider.Factory // TODO this was added to the activity
override fun onCreate(savedInstanceState: Bundle?) {
// Inject external dependencies
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupRecyclerView();
setUpViewModel();
}
private fun setupRecyclerView() {
recycler_view.apply {
layoutManager = LinearLayoutManager(context)
adapter = tripsAdapter
}
}
private fun setUpViewModel(){
val model = ViewModelProviders.of(this, viewModelFactory)[MainActivityViewModel::class.java] // TODO this was changed
model.getTrips().observe(this, Observer { tripsAdapter.trips = it!! })
}
}
I didn't provide the code for including module to dagger component as I hope this is something you already did.
You can read more about this e.g. in this medium article (I'm not author of the article):
#Provides
fun provideTrips(): List<Trip> {
I'm a bit wary of this in the sense that I doubt that it's really Dagger's job to provide this for you directly, but I'll just take that for granted and ignore that for now.
Your code should be:
class MainActivityViewModel #Inject constructor(
trips: List<Trip>
): ViewModel() {
private val tripsLiveData: MutableLiveData<List<Trip>> = MutableLiveData()
init {
tripsLiveData.setValue(trips)
}
fun getTrips() : LiveData<List<Trip>> = tripsLiveData
}
#Module
class TripModule{
#Provides
// #Singleton // <-- possibly should be here?
fun provideTrips(): List<Trip> = listOf(
Trip(100,10),
Trip(200,20)
)
}
#Singleton
#Component(modules = [
AndroidSupportInjectionModule::class,
ActivityBuilder::class,
TripModule::class
])
interface AppComponent{
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(app: MyApplication)
}
class MainActivity : AppCompatActivity() {
#Inject
lateinit var viewModelProvider: Provider<MainActivityViewModel>
// this is specifically not marked with `#Inject`
lateinit var viewModel: MainActivityViewModel
private val tripsAdapter = TripsAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
// Inject external dependencies
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupRecyclerView();
setUpViewModel();
}
private fun setupRecyclerView() {
recycler_view.apply {
layoutManager = LinearLayoutManager(context)
adapter = tripsAdapter
}
}
private fun setUpViewModel(){
viewModel = ViewModelProviders.of(this, object: ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass == MainActivityViewModel::class.java) {
#Suppress("UNCHECKED_CAST")
return viewModelProvider.get() as T
}
throw IllegalArgumentException("Unexpected argument: $modelClass")
}
}).get(MainActivityViewModel::class.java)
viewModel.getTrips().observe(this, Observer {
val trips = it ?: return#observe
tripsAdapter.trips = trips
})
}
}
Aka you should use constructor injection, use the Provider<T> to only get the ViewModel from Dagger when you actually need it, and otherwise initialize it via a ViewModelProviders.Factory so that you actually get the ViewModel from Dagger.

Android dagger: No injector factory bound

I'm using dagger 2 on my android project. At first I'm use only one component in the name of AppComponent and my project works fine. Then I split AppComponent and create these component: ActivityComponent, ContentComponent for different scope. When I was build my project I getting an error:
Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class<project.presenter.activity.MainActivity>
at dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:106)
at dagger.android.AndroidInjection.inject(AndroidInjection.java:61)
at project.AppInjector$registerCallBack$1$handleActivity$2.invoke(AppInjector.kt:77)
at project.AppInjector$registerCallBack$1$handleActivity$2.invoke(AppInjector.kt:53)
at project.AppInjector$registerCallBack$1.injectNow(AppInjector.kt:120)
at project.AppInjector$registerCallBack$1.handleActivity(AppInjector.kt:77)
at project.AppInjector$registerCallBack$1.onActivityCreated(AppInjector.kt:81)
at android.app.Application.dispatchActivityCreated(Application.java:197)
at android.app.Activity.onCreate(Activity.java:1016)
at android.support.v4.app.SupportActivity.onCreate(SupportActivity.java:66)
at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:297)
Another problem is If I add ActivityScope to ActivityComponent I'm getting this error:
Error:(4, 1) error: #project.di.ContentScope project.di.ContentComponent depends on more than one scoped component:
Injectable:
interface Injectable
Components:
#AppScope
#Component(modules = [AndroidInjectionModule::class, AppModule::class, DatabaseModule::class])
interface AppComponent {
interface Builder {
#BindsInstance
fun application(app: App): Builder
fun build(): AppComponent
}
fun inject(app: App)
fun getDatabase(): RoomDatabase
}
#ContentScope
#Component(
dependencies = [AppComponent::class, ActivityComponent::class],
modules = [AndroidInjectionModule::class, ContentModules::class])
interface ContentComponent {
fun inject(favorite: Favorite)
fun inject(contentManager: ContentManager)
fun getObservableManager(): ModuleObservableManager
fun getFavorite(): Favorite
}
#Subcomponent(modules = [ActivityModules::class])
interface ActivityComponent
Modules:
#ActivityScope
#Module(includes = [MainActivityModule::class])
class ActivityModules
#ActivityScope
#Module(includes = [FragmentViewModelModule::class])
abstract class MainActivityModule {
#ActivityScope
#ContributesAndroidInjector(modules = [MainFragmentModule::class])
abstract fun bind(): MainActivity
}
#AppScope
#Module
class AppModule(private val application: Application) {
#AppScope
#Provides
fun provideApplication(): Application = application
#AppScope
#Provides
#ApplicationContext
fun provideContext(): Context = application.applicationContext
}
#ContentScope
#Module
class ContentModules {
val database: RoomDatabase
#Inject
constructor(database: RoomDatabase) {
this.database = database
}
#ContentScope
#Provides
fun provideModuleObservable()
= ModuleObservableManager()
#ContentScope
#Provides
fun provideFavoriteDao()
= database.favoriteDao()
#Provides
fun provideFavorite(dao: FavoriteDao)
= Favorite(dao)
}
#AppScope
#Module
class DatabaseModule {
#AppScope
#Provides
fun provideDatabase(#ApplicationContext context: Context): RoomDatabase =
Room.databaseBuilder(context, RoomDatabase::class.java, RoomDatabase.CONS.NAME)
.allowMainThreadQueries()
.fallbackToDestructiveMigration()
.build()
}
#FragmentScope
#Module
abstract class FragmentViewModelModule {
#Binds
#IntoMap
#ViewModelKey(MainFragmentViewModel::class)
abstract fun bindHomeViewModel(model: MainFragmentViewModel): ViewModel
#Binds
abstract fun bindAppViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
}
#AppScope
class ViewModelFactory #Inject
constructor(private val creators: Map<Class<out ViewModel>, #JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) throw IllegalArgumentException("unknown model class " + modelClass)
try {
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
#MustBeDocumented
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.RUNTIME)
#MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
Scopes:
#Scope
#Retention(AnnotationRetention.RUNTIME)
annotation class AppScope
#Scope
#Retention(AnnotationRetention.RUNTIME)
annotation class ActivityScope
#Scope
#Retention(AnnotationRetention.RUNTIME)
annotation class FragmentScope
#Scope
#Retention(AnnotationRetention.RUNTIME)
annotation class ContentScope
Qualifiers:
#Qualifier
#Retention(AnnotationRetention.RUNTIME)
annotation class ActivityContext
#Qualifier
#Retention(AnnotationRetention.RUNTIME)
annotation class ApplicationContext
App:
class App : Application(), HasActivityInjector {
companion object {
private var instance: App? = null
fun getAppComponent(): AppComponent?
= instance?.appComponent
fun getContentComponent(): ContentComponent?
= instance?.contentComponent
}
#Inject
lateinit var injector: DispatchingAndroidInjector<Activity>
private var appComponent: AppComponent? = null
get() {
if (field == null) field = createAppComponent()
return field
}
private fun createAppComponent(): AppComponent? =
DaggerAppComponent.builder()
.appModule(AppModule(this))
.build()
.also { it.inject(this#App); appComponent = it }
private var contentComponent: ContentComponent? = null
get() {
if (field == null) field = createContentComponent()
return field
}
private fun createContentComponent(): ContentComponent? =
DaggerContentComponent.builder()
.appComponent(appComponent)
.build()
.also { contentComponent = it }
override fun onCreate() {
super.onCreate()
createAppComponent()
AppInjector.init(let { instance = this; this })
}
}
object AppInjector {
fun init(app: App) =
app.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
fun handleActivity(activity: Activity) {
if (activity is FragmentActivity) {
activity.supportFragmentManager.registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentAttached(fm: FragmentManager?, fragment: Fragment?, context: Context?) {
if (fragment is Injectable) {
AndroidSupportInjection.inject(fragment)
}
}
}, true)
}
if (activity is Injectable) AndroidInjection.inject(activity)
}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) = handleActivity(activity)
override fun onActivityStarted(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityDestroyed(activity: Activity) {}
)
}
Manifest:
<application
android:name="project.App"
..
I added the similar project on the github: Project Link

Categories

Resources