Skip to content

Commit

Permalink
From Dagger2 to Kodein
Browse files Browse the repository at this point in the history
  • Loading branch information
AllanHasegawa committed Oct 2, 2017
1 parent 37a79e0 commit 0b9804a
Show file tree
Hide file tree
Showing 16 changed files with 131 additions and 226 deletions.
13 changes: 10 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ repositories {
mavenCentral()
}

kapt {
generateStubs = true
}

dependencies {
def versions = [
kotlin : rootProject.ext.kotlin_version,
Expand All @@ -37,18 +41,19 @@ dependencies {
picasso : '2.5.2',
retrofit : '2.3.0',
leonids : '1.3.1',
dagger2 : '2.11',
kodein : '4.1.0',
koptional : '1.2.0',

junit : '4.12',
mockito : '2.+',
mockitoKotlin: '1.5.0',

espresso : '2.2.2',
]
kapt "com.google.dagger:dagger-compiler:$versions.dagger2"

compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$versions.kotlin"
compile "com.google.dagger:dagger:$versions.dagger2"
compile "com.github.salomonbrys.kodein:kodein:$versions.kodein"
compile "com.github.salomonbrys.kodein:kodein-conf:$versions.kodein"
compile "com.android.support:appcompat-v7:$versions.supportLib"
compile "com.android.support:design:$versions.supportLib"
compile "com.squareup.picasso:picasso:$versions.picasso"
Expand All @@ -59,13 +64,15 @@ dependencies {
exclude group: 'stax', module: 'stax'
exclude group: 'xpp3', module: 'xpp3'
})
compile "com.gojuno.koptional:koptional:$versions.koptional"

testCompile "junit:junit:$versions.junit"
testCompile "org.mockito:mockito-core:$versions.mockito"
testCompile("com.nhaarman:mockito-kotlin:$versions.mockitoKotlin", {
exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib"
})

androidTestCompile "org.jetbrains.kotlin:kotlin-reflect:$versions.kotlin"
androidTestCompile "org.mockito:mockito-android:$versions.mockito"
androidTestCompile("com.nhaarman:mockito-kotlin:$versions.mockitoKotlin", {
exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib"
Expand Down
3 changes: 3 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

# Kodein
-keepattributes Signature
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import android.support.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4
import com.nhaarman.mockito_kotlin.mock
import io.catter2.R
import io.catter2.di.UserDIComponent
import io.catter2.di.UserKodein
import io.catter2.espresso_utils.RecyclerViewItemCountAssertion
import io.catter2.favorites.GetFavoritesUseCase
import org.junit.BeforeClass
Expand All @@ -17,13 +17,13 @@ import org.junit.runner.RunWith
import java.util.*

@RunWith(AndroidJUnit4::class)
class FavoritesActivityTest {
open class FavoritesActivityTest {
companion object {
@BeforeClass
@JvmStatic
fun beforeClass() {
// Warning: The AppDIComponent is still being created by the 'App' class!
UserDIComponent.initialize(mock())
UserKodein.initialize("user")
}
}

Expand Down Expand Up @@ -55,7 +55,7 @@ class FavoritesActivityTest {
}

private fun setUpGetFavoritesResponse(urls: List<String>) {
FavoritesActivityDIModule.testGetFavoritesUseCase =
FavoritesActivityKodein.testGetFavoritesUseCase =
object : GetFavoritesUseCase(mock()) {
override fun getFavorites(callback: (List<String>) -> Unit) {
callback(urls)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import io.catter2.R
import io.catter2.cat_api.FetchCatImagesUseCase
import io.catter2.di.UserDIComponent
import io.catter2.di.UserKodein
import io.catter2.espresso_utils.RecyclerViewItemCountAssertion
import io.catter2.favorites.AddFavoriteUseCase
import org.junit.BeforeClass
Expand All @@ -25,13 +25,13 @@ import org.mockito.Mockito.verify
import java.util.*

@RunWith(AndroidJUnit4::class)
class ListActivityTest {
open class ListActivityTest {
companion object {
@BeforeClass
@JvmStatic
fun beforeClass() {
// Warning: The AppDIComponent is still being created by the 'App' class!
UserDIComponent.initialize(mock())
UserKodein.initialize("user")
}
}

Expand Down Expand Up @@ -61,7 +61,7 @@ class ListActivityTest {
val mock = mock<AddFavoriteUseCase> {
on { addFavoriteUrl("url0") } doReturn true
}
ListActivityDIModule.testAddFavoriteUseCase = mock
ListActivityKodein.testAddFavoriteUseCase = mock

activityRule.launchActivity(Intent())

Expand All @@ -77,12 +77,12 @@ class ListActivityTest {
}

private fun setUpListCatImages(urls: List<String>) {
ListActivityDIModule.testFetchCatImagesUseCase = object : FetchCatImagesUseCase(mock()) {
ListActivityKodein.testFetchCatImagesUseCase = object : FetchCatImagesUseCase(mock()) {
override fun getImagesUrls(callback: (List<String>) -> Unit) {
callback(urls)
}
}
ListActivityDIModule.testAddFavoriteUseCase = // NoOp
ListActivityKodein.testAddFavoriteUseCase = // NoOp
AddFavoriteUseCase(mock())
}
}
12 changes: 2 additions & 10 deletions app/src/main/java/io/catter2/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,13 @@ package io.catter2

import android.app.Application
import android.util.Log
import io.catter2.di.AppDIComponent
import io.catter2.di.AppDIModule
import io.catter2.di.CachedRetrofitCatApiDIModule
import io.catter2.di.AppKodein

class App : Application() {
override fun onCreate() {
super.onCreate()

Log.d("App", "Initialized")
val appDIModule = object : AppDIModule() {
override fun provideAppContext() = this@App
}
AppDIComponent.initialize(appDIModule, CachedRetrofitCatApiDIModule())

// Option if you don't want to cache the cat API responses.
// AppDIComponent.initialize(appDIModule, new RetrofitCatApiDIModule());
AppKodein.initialize(this, useCachedCatApi = true)
}
}
7 changes: 3 additions & 4 deletions app/src/main/java/io/catter2/LoginActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.view.inputmethod.EditorInfo
import io.catter2.di.SharedPrefFavoritesRepoDIModule
import io.catter2.di.UserDIComponent
import io.catter2.di.UserKodein
import io.catter2.favorites_activity.FavoritesActivity
import io.catter2.login.LoginUseCase
import kotlinx.android.synthetic.main.activity_login.*
Expand All @@ -32,7 +31,7 @@ class LoginActivity : AppCompatActivity() {
}

override fun onResume() {
UserDIComponent.instance?.close()
UserKodein.clear()
super.onResume()
}

Expand All @@ -47,7 +46,7 @@ class LoginActivity : AppCompatActivity() {
when (token) {
null -> login_error_tv.visibility = View.VISIBLE
else -> {
UserDIComponent.initialize(SharedPrefFavoritesRepoDIModule(token))
UserKodein.initialize(token)
FavoritesActivity.launch(this)
}
}
Expand Down
11 changes: 0 additions & 11 deletions app/src/main/java/io/catter2/di/CachedRetrofitCatApiDIModule.kt

This file was deleted.

3 changes: 0 additions & 3 deletions app/src/main/java/io/catter2/di/EmptyModuleException.kt

This file was deleted.

7 changes: 0 additions & 7 deletions app/src/main/java/io/catter2/di/RetrofitCatApiDIModule.kt

This file was deleted.

13 changes: 0 additions & 13 deletions app/src/main/java/io/catter2/di/SharedPrefFavoritesRepoDIModule.kt

This file was deleted.

71 changes: 28 additions & 43 deletions app/src/main/java/io/catter2/di/di_app.kt
Original file line number Diff line number Diff line change
@@ -1,52 +1,37 @@
package io.catter2.di

import android.content.Context
import dagger.Component
import dagger.Module
import dagger.Provides
import com.github.salomonbrys.kodein.Kodein
import com.github.salomonbrys.kodein.bind
import com.github.salomonbrys.kodein.singleton
import io.catter2.App
import io.catter2.cat_api.CacheTheCatAPI
import io.catter2.cat_api.RetrofitTheCatAPI
import io.catter2.cat_api.TheCatAPI
import javax.inject.Singleton


@Module
open class AppDIModule {
@Provides
@Singleton
open fun provideAppContext(): Context {
throw EmptyModuleException()
}
}


@Module
open class TheCatAPIDIModule {
@Provides
@Singleton
open fun provideTheCatAPI(): TheCatAPI {
throw EmptyModuleException()
}
}

@Singleton
@Component(modules = arrayOf(AppDIModule::class, TheCatAPIDIModule::class))
abstract class AppDIComponent {
companion object {
var instance: AppDIComponent? = null
private set

fun initialize(appDIModule: AppDIModule, theCatAPIDIModule: TheCatAPIDIModule) {
if (AppDIComponent.instance != null) {
throw RuntimeException("AppDIComponent already initialized.")
import java.security.InvalidParameterException

object AppKodein {
lateinit var kodein: Kodein
private set

fun initialize(appContext: App, useCachedCatApi: Boolean) {
try {
kodein
throw InvalidParameterException("AppKodein already initialized")
} catch (e: UninitializedPropertyAccessException) {
kodein = Kodein {
bind<App>() with singleton { appContext }
bind<Context>() with singleton { appContext }
bind<TheCatAPI>() with singleton {
val service = RetrofitTheCatAPI()
when (useCachedCatApi) {
true -> CacheTheCatAPI(service)
else -> service
}
}
}
AppDIComponent.instance = DaggerAppDIComponent
.builder()
.appDIModule(appDIModule)
.theCatAPIDIModule(theCatAPIDIModule)
.build()
}
}

abstract fun getAppContext(): Context

abstract fun getTheCatAPI(): TheCatAPI
}

71 changes: 24 additions & 47 deletions app/src/main/java/io/catter2/di/di_user.kt
Original file line number Diff line number Diff line change
@@ -1,59 +1,36 @@
package io.catter2.di

import android.content.Context
import dagger.Component
import dagger.Module
import dagger.Provides
import android.util.Log
import com.github.salomonbrys.kodein.Kodein
import com.github.salomonbrys.kodein.bind
import com.github.salomonbrys.kodein.instance
import com.github.salomonbrys.kodein.instanceOrNull
import com.github.salomonbrys.kodein.provider
import com.github.salomonbrys.kodein.singleton
import com.github.salomonbrys.kodein.with
import io.catter2.favorites.FavoritesRepository
import javax.inject.Named
import javax.inject.Scope
import io.catter2.favorites.SharedPrefFavoritesRepository


@Scope
annotation class UserScope
object UserKodein {
var kodein: Kodein? = null
private set


@Module
open class FavoritesRepoDIModule {
@Provides
@UserScope
open fun provideFavoritesRepository(
appContext: Context, @Named("UserToken") userToken: String): FavoritesRepository {
throw EmptyModuleException()
}

@Provides
@Named("UserToken")
@UserScope
open fun provideUserToken(): String {
throw EmptyModuleException()
}
}


@UserScope
@Component(modules = arrayOf(FavoritesRepoDIModule::class),
dependencies = arrayOf(AppDIComponent::class))
abstract class UserDIComponent : AppDIComponent() {
companion object {
var instance: UserDIComponent? = null
private set

fun initialize(module: FavoritesRepoDIModule) {
if (UserDIComponent.instance != null) {
throw RuntimeException("UserDIComponent already initialized.")
fun initialize(userToken: String) {
kodein?.run { throw RuntimeException("UserKodein already initialized.") }
kodein = Kodein {
extend(AppKodein.kodein)
constant("UserToken") with userToken
bind<FavoritesRepository>() with singleton {
Log.i("USER", "Creating FavoritesRepository")
SharedPrefFavoritesRepository(instance(), instance("UserToken"))
}
UserDIComponent.instance = DaggerUserDIComponent.builder()
.appDIComponent(AppDIComponent.instance)
.favoritesRepoDIModule(module)
.build()
}
}

abstract fun getFavoritesRepository(): FavoritesRepository?

fun close() {
getFavoritesRepository()?.clearChangeListener()
UserDIComponent.instance = null
fun clear() {
kodein?.instanceOrNull<FavoritesRepository>()?.clearChangeListener()
kodein = null
}
}

Loading

0 comments on commit 0b9804a

Please sign in to comment.