Dependency Injection with Kotlin for Android newbies! (Koin,Retrofit and Coroutines)

Expectation is to get you up and running with dependency injection with Koin alongside with retrofit and Kotlin Coroutines in a minimal setup. no serious app architecture here !

Gihan Sandaru
3 min readMay 18, 2019
Image credits — https://stackify.com

Koin is not a DI Framework, a serious discussion here

Repo Links😎

  1. 💉 Koin — https://github.com/InsertKoinIO/koin
  2. 🌎 Retrofit — https://square.github.io/retrofit/
  3. 🔌 retrofit2-kotlin-coroutines-adapter — https://github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter

Why Koin? ( in comparison with dagger 2 )

Also I saw few downpoints

  • not a proper DI framework but a service locator (read more)
  • No compile time dependency tree validations , you’ll know everything on runtime ? maybe not great for large projects.

TL;DR

kotlin-gradle-plugin_version = '1.3.21'
gradle_version = '3.4.1'
  1. Create a kt project in android studio and setup below dependencies
//Koin
implementation 'org.koin:koin-android:2.0.0-GA'

//Moshi
implementation "com.squareup.moshi:moshi-kotlin:1.8.0"

//Retrofit2
implementation "com.squareup.retrofit2:retrofit:2.5.0"
implementation "com.squareup.retrofit2:converter-moshi:2.5.0"
implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2"

2. Retrofit basics

Implementing retofit is pretty straightforward, first we implement the interface which contains the endpoints that we are going to call to

interface GitHubService {

@GET("users/{user}/repos")
fun listRepos(@Path("user") user: String):
Deferred<Response<List<Repo>>>
}

See Deferred<Response<List<Repo>>> , Deferred value is a non-blocking cancellable future — it is a Job that has a result
Repo” is the response model object for github search query (get it here)

Next we create the retrofit instance !

Koin needs a list of modules that need to be injected as a parameter ,for this I will create a class named “GitHubServiceAPI”, this class has a getGithubService function which returns a instance of GitHubService

class GitHubServiceAPI { 

fun getGitHubService() : GitHubService {

val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(MoshiConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()

return retrofit.create(GitHubService::class.java)
}
}

next we’ll setup koin to inject our GitHub service API to GlobelContext (read more )

this can be done in your Main Activity too , but I’ve created a class Extending Application to encapsulate koin setup from startup activity ( read on Why to extend an Application class?. )

Don’t forget to add this line inside the application tag of your AndroidManifest.xml

android:name=".MyApplication"

also internet permissions

<uses-permission android:name="android.permission.INTERNET" />

MyApplication.kt

class MyApplication : Application() {


var listofModules = module {
single { GitHubServiceAPI() }
}


override fun onCreate() {
super.onCreate()

startKoin {
androidLogger()
androidContext(this@MyApplication)
modules(listofModules)
}
}
}

inside list of modules , I’ve added GitHubSeriviceAPI as single which will genarete a singleton object, if we use as factory { GitHubServiceAPI() } it will generate new instance each time you ask for this definition.

finally , get to your startup activity and call the githubservice !

learn more on coroutines https://android.jlelse.eu/coroutines-basic-terminologies-and-usage-b4242bd1b2a4

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Injected GithubServiceAPI
val serviceAPI: GitHubServiceAPI = get()

val gitHubService: GitHubService = serviceAPI.getGitHubService()

val call = gitHubService.listRepos("gsandaru")

CoroutineScope(Dispatchers.IO).launch {

val request = gitHubService.listRepos("gsandaru")

withContext(Dispatchers.IO) {
try {
val response = request.await()
if (response.isSuccessful) {

var data : List<Repo>? = response.body();

Log.d("MainActicity",
"Success ${data?.size} Repos Found")

} else {

Log.d("MainActicity",
"Error : Status ${response.code()} ")

}
} catch (e: Exception) {
Log.d("MainActicity",
"Exception ${e.message}")

}
}
}
}
}

get sourcecode here( https://github.com/gsandaru/Kotlin-Samples) , let me know any mistakes and glitches of this article in comments !

Happy Coding!

— — — — — —

LinkedIn — https://www.linkedin.com/in/gihansandaru/

--

--