DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Fevzi Γ–mΓΌr Tekin
Fevzi Γ–mΓΌr Tekin

Posted on

Dependencies Injection with Koin

Crepe

Hello to everyone,
In this article, I will tell you why I prefer Koin (small and medium-sized projects) when there is a library such as Dagger and the Dependencies Injection principle, which is one of the five pillars of S.O.L.I.D.

WHAT'S DEPENDENCIES INJECTION?

Simply speaking of dependencies injection, Dependency Injection is mainly used for the control and management of dependencies.

How do we manage to control and manage dependencies? If you're asking why we should use it, you can get more detailed information about this from the following two articles.


A quick intro to Dependency Injection: what it is, and when to use it


Dependency Injection in Android with Dagger 2 and Kotlin

What is Koin?

Koin is a simple and powerful dependencies injection library. It's written with Kotlin.

Why should we use Koin when there is Dagger? Why do I use Koin?

The reason I use Koin; Dagger; it comes to me as a structure that is difficult to learn and practice because of the formation of too many classes and the mixed structure. I use Koin because of its simpler structure and light weight.

Dagger to explain when you should prefer Koin; a simple project with both Dagger and Koin to create the differences between the two Let's examine one by one.

KOIN VS DAGGER

Dagger and Koin libraries will be compared through a project using MVVM.

  • Comparison of DI packet structure
Crepe

In the first picture, we see the classes and package structure used by Dagger and the second picture to create Koin içins dependencies. Koin is being created with a simpler and less number of classes.

  • Number of codes before and after compile
Crepe

As seen in the example, there is a half-way difference between the number of codes generated by the coin and dagger. This shows that Koin is a lighter structure.

  • Build Time
    Koin:
    BUILD SUCCESSFUL in 19s
    120 actionable tasks: 112executed, 7up-to-date

    Dagger:
    BUILD SUCCESSFUL in 21s
    118 actionable tasks: 112 executed, 7up-to-date
Enter fullscreen mode Exit fullscreen mode
  • Setup/Package and Class Structure

Dagger

Implementation the Dagger Sdk to the project;

    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    kapt "com.google.dagger:dagger-android-processor:$dagger_version"
    implementation "com.google.dagger:dagger:$dagger_version"
Enter fullscreen mode Exit fullscreen mode

Classes for injection of activity, fragment and viewmodels;

  • ActivityModule
  @Module
abstract class ActivityModule {
    @ContributesAndroidInjector(modules = [FragmentModule::class])
    abstract fun contributeMainActivity(): MainActivity

    //Add your other activities here
}

Enter fullscreen mode Exit fullscreen mode
  • FragmentModule
    @Module
    abstract class FragmentModule {
        @ContributesAndroidInjector
        abstract fun contributeNewsFragment(): NewsFragment

        @ContributesAndroidInjector
        abstract fun contributeNewDetailsFragment(): NewDetailsFragment

    }

Enter fullscreen mode Exit fullscreen mode
  • ViewModelModule
    @Module
    abstract class ViewModelModule {

        @Binds
        abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

        @Binds
        @IntoMap
        @ViewModelKey(MainViewModel::class)
        abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel

        @Binds
        @IntoMap
        @ViewModelKey(NewsViewModel::class)
        abstract fun bindNewsViewModel(newsViewModel:  NewsViewModel): ViewModel

        @Binds
        @IntoMap
        @ViewModelKey(NewDetailsViewModel::class)
        abstract fun bindNewDetailsViewModel(newDetailsViewModel:  NewDetailsViewModel): ViewModel
    }

Enter fullscreen mode Exit fullscreen mode

After creating the modules and components to be injected into the project;


    Class BaseApplication : Application(), HasActivityInjector { 
  @Inject
      lateinit var dispatchingAndroidInjector:    DispatchingAndroidInjector<Activity>

    override fun activityInjector() = dispatchingAndroidInjector

    fun initDagger() {
       DaggerAppComponent
          .builder()
          .application(this)
          .build()
          .inject(this)
      }
    }

Enter fullscreen mode Exit fullscreen mode

Koin

Δ°mplementation the Koin SDK to the project


  implementation "org.koin:koin-android-viewmodel:$koin_version"

Enter fullscreen mode Exit fullscreen mode

The difference of Koin from dagger; Instead of creating separate classes for Activity, fragment, and viewmodule, we do it all in one class. This will take care of everything in one class and prevent branching.

  • App Module

  package com.fevziomurtekin.di

    import androidx.room.Room
    import com.fevziomurtekin.hackernewsapp.data.room.*
    import com.fevziomurtekin.hackernewsapp.ui.main.MainViewModel
    import com.fevziomurtekin.hackernewsapp.ui.newdetails.NewsDetailsViewModel
    import com.fevziomurtekin.hackernewsapp.ui.news.NewsViewModel
    import com.fevziomurtekin.hackernewsapp.util.ApplicationSchedulerProvider
    import com.fevziomurtekin.hackernewsapp.util.SchedulerProvider
    import org.koin.android.architecture.ext.viewModel
    import org.koin.android.ext.koin.androidApplication
    import org.koin.dsl.module.applicationContext



    val appModule = applicationContext {


        viewModel { MainViewModel(get(),get()) }

        viewModel { NewsViewModel(get()) }

        viewModel { NewsDetailsViewModel(get()) }

        // ItemRepository providers.
        bean { ItemRepositoryImpl(get(),get()) as ItemRepository }

        bean { UserRepositoryImpl(get(),get()) as UserRepository }

        // provider to Room database.
        bean {
            Room.databaseBuilder(androidApplication(),Database::class.java,"hackernews-db")
                .allowMainThreadQueries()
                .fallbackToDestructiveMigration()
                .build()
        }

        bean { ApplicationSchedulerProvider() as SchedulerProvider }

        // Expose ItemDao directly
        bean { get<Database>().itemDao() as ItemDao }

        // Expose UserDao directly
        bean { get<Database>().userDao() }

    }


    val onlineNewsApp = listOf(appModule, remoteModule)

Enter fullscreen mode Exit fullscreen mode

Koin and the components of Koin that we need to know when writing this article in AppModule

  • get () β†’ This component is usually used to inject into constructive method (you can only inject the structures defined in App.module with get ())
  • factory β†’This component is used to give you a new sample every time you request it.
  • bean β†’ This component is used when performing single identification.
  • name = This component is required when you want to have more than one instance of the same class in different classes.

For Koin to start after you create the modules and components;

    package com.fevziomurtekin.hackernewsapp

    import android.app.Application
    import com.fevziomurtekin.di.onlineNewsApp
    import org.koin.android.ext.android.startKoin

    class BaseApplication : Application(){

        override fun onCreate() {
            super.onCreate()

            startKoin(this, onlineNewsApp)

        }
    }

Enter fullscreen mode Exit fullscreen mode

After injecting the Koini into our project, we call the mainViewModel we created in AppModule as an example;

val viewModel by viewModel ()

Resources and Conclusion


Koin Github


Getting started Koin Android

I tried to explain why I prefer Koin, how I use it, and how much if I use dagger and coin on a simple project, as far as I can. More information can be found at. Next

Link to the project I developed with Koin:



HackerNewsApp

Top comments (1)

Collapse
piannaf profile image
Justin Mancinelli

Nice walkthrough. Would love to see your writing on Koin 2.0

πŸ€” Did you know?

Β 
🌚 Dark mode is available in Settings.