Skip to content

Commit 0d2e737

Browse files
committed
feat: migrate from Hilt to Koin for simplicity
1 parent 1a23053 commit 0d2e737

23 files changed

+132
-176
lines changed

app/build.gradle.kts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ plugins {
1818
id("org.jetbrains.kotlin.android")
1919
id("kotlin-android")
2020
id("kotlin-kapt")
21-
// id("com.google.devtools.ksp")
22-
id("com.google.dagger.hilt.android")
2321
}
2422

2523
android {
@@ -65,9 +63,6 @@ android {
6563
dependencies {
6664
//Compile time dependencies
6765
kapt("androidx.lifecycle:lifecycle-compiler:2.6.1")
68-
kapt("com.google.dagger:hilt-android-compiler:2.46.1")
69-
70-
implementation("com.google.dagger:hilt-android:2.46.1")
7166

7267
// Application dependencies
7368
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22")
@@ -80,6 +75,11 @@ dependencies {
8075
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")
8176
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
8277

78+
79+
//koin
80+
implementation("io.insert-koin:koin-android:3.4.3")
81+
// implementation("io.insert-koin:koin-android-viewmodel:3.4")
82+
8383
// Update from here
8484
implementation("androidx.cardview:cardview:1.0.0")
8585
implementation("androidx.recyclerview:recyclerview:1.3.0")
@@ -104,7 +104,6 @@ dependencies {
104104
androidTestImplementation("androidx.test.ext:junit:1.1.5")
105105
androidTestImplementation("androidx.test:rules:1.5.0")
106106
androidTestImplementation("androidx.test.espresso:espresso-intents:3.5.1")
107-
androidTestImplementation("com.google.dagger:hilt-android-testing:2.46.1")
108107

109108
// Development dependencies
110109
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.12")

app/src/main/kotlin/com/fernandocejas/sample/AndroidApplication.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,25 @@
1616
package com.fernandocejas.sample
1717

1818
import android.app.Application
19-
import dagger.hilt.android.HiltAndroidApp
19+
import com.fernandocejas.sample.core.di.appModule
20+
import org.koin.android.ext.koin.androidContext
21+
import org.koin.android.ext.koin.androidLogger
22+
import org.koin.core.context.GlobalContext.startKoin
2023

21-
@HiltAndroidApp
22-
class AndroidApplication : Application()
24+
class AndroidApplication : Application() {
25+
override fun onCreate() {
26+
super.onCreate()
27+
28+
/**
29+
* Dependency Injection Initialization via Koin.
30+
*
31+
* @see [https://insert-koin.io/docs/setup/koin]
32+
* @see [https://insert-koin.io/docs/reference/koin-android/start/]
33+
*/
34+
startKoin {
35+
androidContext(this@AndroidApplication)
36+
androidLogger()
37+
modules(appModule)
38+
}
39+
}
40+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.fernandocejas.sample.core.di
2+
3+
import com.fernandocejas.sample.core.navigation.Navigator
4+
import com.fernandocejas.sample.core.platform.NetworkHandler
5+
import com.fernandocejas.sample.features.login.Authenticator
6+
import com.fernandocejas.sample.features.movies.GetMovieDetails
7+
import com.fernandocejas.sample.features.movies.GetMovies
8+
import com.fernandocejas.sample.features.movies.MovieDetailsAnimator
9+
import com.fernandocejas.sample.features.movies.MovieDetailsViewModel
10+
import com.fernandocejas.sample.features.movies.MoviesAdapter
11+
import com.fernandocejas.sample.features.movies.MoviesRepository
12+
import com.fernandocejas.sample.features.movies.MoviesService
13+
import com.fernandocejas.sample.features.movies.MoviesViewModel
14+
import com.fernandocejas.sample.features.movies.PlayMovie
15+
import okhttp3.OkHttpClient
16+
import org.koin.androidx.viewmodel.dsl.viewModel
17+
import org.koin.androidx.viewmodel.dsl.viewModelOf
18+
import org.koin.core.module.dsl.factoryOf
19+
import org.koin.core.module.dsl.singleOf
20+
import org.koin.dsl.bind
21+
import org.koin.dsl.module
22+
import retrofit2.Retrofit
23+
import retrofit2.converter.gson.GsonConverterFactory
24+
25+
val appModule = module {
26+
// Core
27+
singleOf(::retrofit)
28+
singleOf(::NetworkHandler)
29+
singleOf(::Navigator)
30+
31+
// Login Feature
32+
singleOf(::Authenticator)
33+
34+
// Movies Feature
35+
factoryOf(::MoviesService)
36+
factory { MoviesRepository.Network(get(), get()) } bind MoviesRepository::class
37+
// Movies
38+
viewModelOf(::MoviesViewModel)
39+
factoryOf(::GetMovies)
40+
factoryOf(::MoviesAdapter)
41+
// Movie Details
42+
viewModelOf(::MovieDetailsViewModel)
43+
factoryOf(::GetMovieDetails)
44+
factoryOf(::PlayMovie)
45+
factoryOf(::MovieDetailsAnimator)
46+
}
47+
48+
fun retrofit(): Retrofit {
49+
return Retrofit.Builder()
50+
.baseUrl("https://raw.githubusercontent.com/android10/Sample-Data/master/Android-CleanArchitecture-Kotlin/")
51+
.client(OkHttpClient.Builder().build())
52+
.addConverterFactory(GsonConverterFactory.create())
53+
.build()
54+
}

app/src/main/kotlin/com/fernandocejas/sample/core/di/ApplicationModule.kt

Lines changed: 0 additions & 57 deletions
This file was deleted.

app/src/main/kotlin/com/fernandocejas/sample/core/extension/String.kt renamed to app/src/main/kotlin/com/fernandocejas/sample/core/extension/Strings.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@
1616
package com.fernandocejas.sample.core.extension
1717

1818
fun String.Companion.empty() = ""
19+
20+
fun emptyString() = ""

app/src/main/kotlin/com/fernandocejas/sample/core/navigation/Navigator.kt

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,15 @@ import android.view.View
2323
import android.widget.ImageView
2424
import androidx.core.app.ActivityOptionsCompat
2525
import androidx.fragment.app.FragmentActivity
26-
import com.fernandocejas.sample.core.extension.empty
26+
import com.fernandocejas.sample.core.extension.emptyString
2727
import com.fernandocejas.sample.features.login.Authenticator
2828
import com.fernandocejas.sample.features.login.LoginActivity
2929
import com.fernandocejas.sample.features.movies.MovieDetailsActivity
3030
import com.fernandocejas.sample.features.movies.MovieView
3131
import com.fernandocejas.sample.features.movies.MoviesActivity
32-
import javax.inject.Inject
33-
import javax.inject.Singleton
3432

3533

36-
@Singleton
37-
class Navigator
38-
@Inject constructor(private val authenticator: Authenticator) {
34+
class Navigator(private val authenticator: Authenticator) {
3935

4036
private fun showLogin(context: Context) =
4137
context.startActivity(LoginActivity.callingIntent(context))
@@ -58,8 +54,8 @@ class Navigator
5854
activity.startActivity(intent, activityOptions.toBundle())
5955
}
6056

61-
private val VIDEO_URL_HTTP = "http://www.youtube.com/watch?v="
62-
private val VIDEO_URL_HTTPS = "https://www.youtube.com/watch?v="
57+
private val videoUrlHttp = "http://www.youtube.com/watch?v="
58+
private val videoUrlHttps = "https://www.youtube.com/watch?v="
6359

6460
fun openVideo(context: Context, videoUrl: String) {
6561
try {
@@ -71,10 +67,10 @@ class Navigator
7167

7268
private fun createYoutubeIntent(videoUrl: String): Intent {
7369
val videoId = when {
74-
videoUrl.startsWith(VIDEO_URL_HTTP) -> videoUrl.replace(VIDEO_URL_HTTP, String.empty())
75-
videoUrl.startsWith(VIDEO_URL_HTTPS) -> videoUrl.replace(
76-
VIDEO_URL_HTTPS,
77-
String.empty()
70+
videoUrl.startsWith(videoUrlHttp) -> videoUrl.replace(videoUrlHttp, emptyString())
71+
videoUrl.startsWith(videoUrlHttps) -> videoUrl.replace(
72+
videoUrlHttps,
73+
emptyString()
7874
)
7975
else -> videoUrl
8076
}

app/src/main/kotlin/com/fernandocejas/sample/core/navigation/RouteActivity.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,11 @@ package com.fernandocejas.sample.core.navigation
1717

1818
import android.os.Bundle
1919
import androidx.appcompat.app.AppCompatActivity
20-
import dagger.hilt.android.AndroidEntryPoint
21-
import javax.inject.Inject
20+
import org.koin.android.ext.android.inject
2221

23-
@AndroidEntryPoint
2422
class RouteActivity : AppCompatActivity() {
2523

26-
@Inject
27-
internal lateinit var navigator: Navigator
24+
private val navigator: Navigator by inject()
2825

2926
override fun onCreate(savedInstanceState: Bundle?) {
3027
super.onCreate(savedInstanceState)

app/src/main/kotlin/com/fernandocejas/sample/core/platform/BaseActivity.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@ import android.os.Bundle
1919
import androidx.appcompat.app.AppCompatActivity
2020
import com.fernandocejas.sample.core.extension.inTransaction
2121
import com.fernandocejas.sample.databinding.ActivityLayoutBinding
22-
import dagger.hilt.android.AndroidEntryPoint
2322

2423
/**
2524
* Base Activity class with helper methods for handling fragment transactions and back button
2625
* events.
2726
*
2827
* @see AppCompatActivity
2928
*/
30-
@AndroidEntryPoint
3129
abstract class BaseActivity : AppCompatActivity() {
3230

3331
private lateinit var binding: ActivityLayoutBinding

app/src/main/kotlin/com/fernandocejas/sample/core/platform/BaseFragment.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,12 @@ import com.fernandocejas.sample.R.color
2424
import com.fernandocejas.sample.core.extension.appContext
2525
import com.fernandocejas.sample.core.extension.viewContainer
2626
import com.google.android.material.snackbar.Snackbar
27-
import dagger.hilt.android.AndroidEntryPoint
2827

2928
/**
3029
* Base Fragment class with helper methods for handling views and back button events.
3130
*
3231
* @see Fragment
3332
*/
34-
@AndroidEntryPoint
3533
abstract class BaseFragment : Fragment() {
3634

3735
open fun onBackPressed() {}

app/src/main/kotlin/com/fernandocejas/sample/core/platform/NetworkHandler.kt

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,22 @@ import android.content.Context
1919
import android.net.NetworkCapabilities
2020
import android.os.Build
2121
import com.fernandocejas.sample.core.extension.connectivityManager
22-
import dagger.hilt.android.qualifiers.ApplicationContext
23-
import javax.inject.Inject
24-
import javax.inject.Singleton
2522

2623
/**
2724
* Injectable class which returns information about the network connection state.
2825
*/
29-
@Singleton
30-
class NetworkHandler
31-
@Inject constructor(@ApplicationContext private val context: Context) {
26+
class NetworkHandler(private val context: Context) {
3227
fun isNetworkAvailable(): Boolean {
3328
val connectivityManager = context.connectivityManager
29+
val network = connectivityManager.activeNetwork ?: return false
30+
val activeNetwork = connectivityManager.getNetworkCapabilities(network) ?: return false
3431

35-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
36-
val network = connectivityManager.activeNetwork ?: return false
37-
val activeNetwork =
38-
connectivityManager.getNetworkCapabilities(network) ?: return false
39-
40-
return when {
41-
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
42-
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
43-
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
44-
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> true
45-
else -> false
46-
}
47-
} else {
48-
@Suppress("DEPRECATION") val networkInfo =
49-
connectivityManager.activeNetworkInfo ?: return false
50-
@Suppress("DEPRECATION")
51-
return networkInfo.isConnected
32+
return when {
33+
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
34+
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
35+
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
36+
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> true
37+
else -> false
5238
}
5339
}
5440
}

0 commit comments

Comments
 (0)