Koin on modularization: How to use it?

Koin on modularization: How to use it?

posted Originally published at dev.to 3 min read

What is Modularization in Android?

Modularization in Android means breaking an app into smaller, independent modules instead of keeping all code in a single project. Each module has its own responsibility and can be developed, tested, and maintained separately.

Basic Prerequisites to Understand Modularization

Before learning modularization, you should be familiar with:

  • Android Project Structure – Understanding how an app is built using
    app/src/main.
  • Gradle & Dependencies – Knowing how dependencies are
    managed in build.gradle.kts.
  • Packages & Code Organization – Basics
    of organizing files using packages.
  • Types of Android Modules – App
    Module (Main application)
  • Library Module (Reusability across
    projects)
  • Feature Module (For dynamic delivery in large apps)

Why Modularization?

  • ✅ Faster Build Times – Only modified modules get compiled.
  • ✅ Better
    Code Maintainability – Easier to manage and scale.
  • ✅ Reusability –
    Common features like networking or authentication can be shared
    across projects.
  • ✅ Parallel Development – Teams can work on different
    modules independently.

Today we are going to set up step by step how to use Koin in modularization with viewModel.

Before we get started. Create some new modules and structured them like this:

Step 1

You have to determine what koin gradle version you want to use. For this tutorial, I use 2.2.2 version. Define the gradle into di module

implementation "io.insert-koin:koin-android:2.2.2"
implementation "io.insert-koin:koin-androidx-viewmodel:2.2.2"
implementation "io.insert-koin:koin-androidx-scope:2.2.2"

Step 2

After you have decided koin version you'd use, add other dependency your project would need for injecting to koin in di module as well. In this tutorial I want to inject Retrofit for network, AndroidX Room for local DB, Shared Preferences, ViewModel for managing data, and Coroutine for threading

implementation "io.insert-koin:koin-android:2.2.2"
implementation "io.insert-koin:koin-androidx-viewmodel:2.2.2"
implementation "io.insert-koin:koin-androidx-scope:2.2.2"
implementation "javax.inject:javax.inject:1"

implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"

implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2"

implementation "androidx.room:room-runtime:2.4.2"
kapt "androidx.room:room-compiler:2.4.2"
implementation "androidx.room:room-ktx:2.4.2"

Step 3

Define Network Module, Api Module, Shared Preferences Module, Room Module, and ViewModel Module (we also use UseCase and Repository module for clean architecture principle)

class ApiModule {
    companion object {
        val apiModule = module(override = true) {
            single { provideDisneyApi(get()) }
        }

        fun provideDisneyApi(retrofit: Retrofit): Api {
            return retrofit.create(Api::class.java)
        }
    }
}

class NetworkModule  {
    companion object {
        private fun httpInterceptor() = HttpLoggingInterceptor().apply {
            return HttpLoggingInterceptor { _ ->
            }.apply {
                level = HttpLoggingInterceptor.Level.BODY
            }
        }

        fun provideNetworkHandler(context: Context) = NetworkHandler(context)

        fun provideOkHttpClient() : OkHttpClient {
            return Builder.initInterceptor(httpInterceptor())
        }

        fun provideRetrofitService(okHttpClient: OkHttpClient): Retrofit {
            return Builder.initRetrofit(okHttpClient)
        }
    }
}

class SharedPrefModule {
    companion object {
        fun providePreference(context: Context) : SharedPreferences {
            return context.getSharedPreferences("SharedPreferenceName", Context.MODE_PRIVATE)
        }
    }
}

class RoomModule {
    companion object {
        fun provideRoom(context: Context) : DBConfig {
            return Room.databaseBuilder(context, DBConfig::class.java, "db_sample")
                .fallbackToDestructiveMigration()
                .build()
        }
    }
}

class RepositoryModule {
    companion object {
        val repositoryModule = module(override = true) {
            single<CharacterRepository> { return@single CharacterRepositoryImpl(get(), get()) }
        }
    }
}

class UseCaseModule {
    companion object {
        val useCaseModule = module(override = true) {
            single<CharacterUseCase> { return@single CharacterUseCaseImpl(get()) }
        }
    }
}

class ViewModelModule {
    companion object {
        val viewModelModule = module(override = true) {
            viewModel { GamesListVM(get(), get()) }
            viewModel { GamesDetailVM(get(), get()) }
            viewModel { GamesFavoriteVM(get(), get(), get()) }
        }
    }
}

After you add them all, locate and categorize module that you prioritize as a 'core' module and wrap them into AppModule class. In this tutorial I'll wrap retrofit, room, and shared preferences module like this:

val MainAppModule = module(override = true) {
    single { NetworkModule.provideOkHttpClient() }
    single { NetworkModule.provideRetrofitService(get()) }
    single { NetworkModule.provideNetworkHandler(androidContext()) }
    single { RoomModule.provideRoom(androidContext()) }
    single { SharedPrefModule.providePreference(androidContext()) }
}

Step 4

Call them with StartKoin in Application Class in App Module (default module). I will call ViewModel, Repository, Usecase, and Api module as same level with MainApp Module

class DisneyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidLogger(Level.ERROR)
            androidContext(this@DisneyApp)
            modules(MainAppModule, ApiModule.apiModule, RepositoryModule.repositoryModule,
                UseCaseModule.useCaseModule, ViewModelModule.viewModelModule
            )
        }
    }
}

And Voila! Congratulation you've built Koin in modular version. it's easy isn't it?

Happy Coding :)

Sample project: Github link

0 votes
0 votes
0 votes

More Posts

React Native Quote Audit - USA

kajolshah - Mar 2

Koin vs Dagger 2 vs Hilt: Which should we use?

Mikkel Septiano - Apr 22, 2025

Koin vs Hilt

samseptiano - Mar 16, 2025

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

BelZSpeedScann Ismoy

Ismoy - Aug 29, 2025
chevron_left

Related Jobs

View all jobs →

Commenters (This Week)

1 comment
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!