Skip to content

Latest commit

 

History

History
90 lines (78 loc) · 3.54 KB

DI-Dagger.md

File metadata and controls

90 lines (78 loc) · 3.54 KB

DI - Use with Dagger

A Kotlin android architecture with Google Architecture Components

1 How to use it?

1.1 Import dependency

In app level build.gradle add these dependencies that will be needed to add Dagger and thus Dependency injection.

       // dagger2 android
       kapt "com.google.dagger:dagger-android-processor:$dagger_version"
       implementation "com.google.dagger:dagger-android:$dagger_version"
       implementation "com.google.dagger:dagger-android-support:$dagger_version"
       kapt "com.google.dagger:dagger-compiler:$dagger_version"

1.2 Basic implementation steps

Define a ViewModelFactory that will inject ViewModel providers as soon as they will be needed and will add them to a map so they are as singleton instances. You will have to add all the ViewModels you create to this map and to the constructor.

@Singleton
class ViewModelFactory @Inject constructor(application: Application
// ... add other view model providers here
, sampleViewModelProvider: Provider<SampleViewModel>) : ViewModelProvider.Factory {
    
    private val mMapProvider = HashMap<Class<out ViewModel>, Provider<out ViewModel>>()
    private val defaultFactory: ViewModelProvider.AndroidViewModelFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application)

    init {
        mMapProvider[SampleViewModel::class.java] = sampleViewModelProvider
        // ... add other view model providers to the map here
    }
    
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return if (mMapProvider.containsKey(modelClass)) {
            mMapProvider[modelClass]!!.get() as T
        } else {
            defaultFactory.create(modelClass)
        }
    }
}

Define an application component that will provide the created ViewModelFactory.

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class])
interface ApplicationComponent : AndroidInjector<DaggerApplication> {
    fun getViewModelFactory(): ViewModelFactory
}

Define a ViewModel. By using Dagger, you can create the instance of the view model through the @Inject annotation. Moreover, usecases will be injected instead of being instantiated through reflection.

class SampleViewModel @Inject constructor(sampleUsecase: SampleUsecase
// you can add all possible usecases here as parameters of the ViewModel
) : ViewModel() {
     // actions can use instances of the injected UseCases instead of the class
     val sampleAction = Action.Builder<None, None, None>()
            .useCase(sampleUsecase)
            .buildWithUiModel { None }
    
}

UseCases are written in a similar way: the only difference is that we use the @Inject annotation here and we define our repositories as constructor parameters instead of creating them.

class SampleUsecase @Inject constructor(
// optional repo that you can add as constrtor parameters
private val sampleRepo: SampleRepo) : UseCase<None, None>() {
    override suspend fun run(params: None): Either<Failure, None> {
        // optionally you can perform async operations here.
        return Either.Right(None)
    }
}
@Singleton
class AuthenticationRepo @Inject constructor() {
    // define here your repository methods (DataBase calls, wev)
}

You are now ready to use your view model inside your Activity/Fragment by injecting the ViewModelFactory and lazy initializing it.

@Inject
lateinit var factory: ViewModelFactory
private val viewModel: SampleViewModel by lazy {
    ViewModelProviders.of(this, factory).get(SampleViewModel::class.java)
}