Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Commit

Permalink
Introduce new compact DSL for module declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
svenjacobs committed Feb 8, 2019
1 parent a9ed069 commit d3b76ab
Show file tree
Hide file tree
Showing 33 changed files with 379 additions and 196 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## Version 1.3.0

_2019-02-08_

* Add a new, compact DSL for module declarations.
**Imports must be updated!** Either use `org.rewedigital.katana.dsl.classic` or the new
`org.rewedigital.katana.dsl.compact`:
```kotlin
createModule {
factory { MyDependencyA() }
singleton { MyDependencyB() }
}
```
* Update Kotlin version to 1.3.21

## Version 1.2.8

_2019-02-06_
Expand Down
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ val myModule = createModule {

// Each binding starts with bind<T>()
// A "factory" declaration means that this dependency is instantiated every time when it's requested
bind<MyDependency> { factory { MyDependency() } }
factory { MyDependency() }

// A "singleton" declaration means that this dependency is only instantiated once (per component)
bind<AnotherDependency> { singleton { AnotherDependency() } }
singleton { AnotherDependency() }

// See how transitive dependencies can be injected with get() within the module's scope
bind<YetAnotherDependency> { factory { YetAnotherDependency(get<MyDependency>(), get<AnotherDependency>()) } }
factory { YetAnotherDependency(get<MyDependency>(), get<AnotherDependency>()) }

// Use named bindings when the type is not unique (there might be more Strings)
bind<String>("globalId") { singleton { "SOME_GLOBAL_ID" } }
singleton(name = "globalId") { "SOME_GLOBAL_ID" }

// Use "eagerSingleton" for singleton instances which are instantiated as soon as the component
// is created and not lazily the first time it's requested
bind<SomeEagerDependency> { eagerSingleton { SomeEagerDependency() } }
eagerSingleton { SomeEagerDependency() }
}
```

Expand Down Expand Up @@ -86,11 +86,11 @@ dependencies are declared. The following code will result in an `OverrideExcepti
```kotlin
createModule {

bind<MyProvider<Int>> { factory { MyProvider<Int>(1337) } }
factory { MyProvider<Int>(1337) }

bind<MyProvider<String>> { factory { MyProvider<String>("Hello world") } }
factory { MyProvider<String>("Hello world") }

bind<MyDependency> { factory { MyDependency(get(), get()) } }
factory { MyDependency(get(), get()) }
}
```

Expand All @@ -99,11 +99,11 @@ Luckily Katana provides a solution for this! Just use named injection :)
```kotlin
createModule {

bind<MyProvider<Int>>("intProvider") { factory { MyProvider<Int>(1337) } }
factory(name = ""intProvider"") { MyProvider<Int>(1337) }

bind<MyProvider<String>>("stringProvider") { factory { MyProvider<String>("Hello world") } }
factory(name = "stringProvider") { MyProvider<String>("Hello world") }

bind<MyDependency> { factory { MyDependency(get("intProvider"), get("stringProvider")) } }
factory { MyDependency(get("intProvider"), get("stringProvider")) }
}
```

Expand All @@ -117,17 +117,17 @@ necessary. For example:
```kotlin
val commonModule = createModule {

bind<MyCommonDependency> { singleton { MyCommonDependency() } }
singleton { MyCommonDependency() }
}

val engineModule = createModule {

bind<MyEngine> { factory { MyEngineImpl(get<MyCommonDependency>()) } }
factory<MyEngine> { MyEngineImpl(get<MyCommonDependency>()) }
}

val testEngineModule = createModule {

bind<MyEngine> { factory { MyTestEngine(get<MyCommonDependency>()) } }
factory<MyEngine> { MyTestEngine(get<MyCommonDependency>()) }
}

val productionComponent = createComponent(commonModule, engineModule)
Expand All @@ -145,9 +145,9 @@ class B(a: A)

val module = createModule {

bind<A> { singleton { A(get()) } }
singleton { A(get()) }

bind<B> { singleton { B(get()) } }
singleton { B(get()) }
}

val component = createComponent(module)
Expand All @@ -173,9 +173,9 @@ class B2(a2: A2)
val module = createModule {

// See how lazy() is used here instead of get()
bind<A2> { singleton { A2(lazy()) } }
singleton { A2(lazy()) }

bind<B2> { singleton { B2(get()) } }
singleton { B2(get()) }
}

val component = createComponent(module)
Expand All @@ -196,9 +196,9 @@ a repository to your project. Then add the following dependencies:

```gradle
dependencies {
implementation 'org.rewedigital.katana:katana-core:1.2.8'
implementation 'org.rewedigital.katana:katana-core:1.3.0'
// Use this artifact for Katana on Android
implementation 'org.rewedigital.katana:katana-android:1.2.8'
implementation 'org.rewedigital.katana:katana-android:1.3.0'
}
```

Expand Down
3 changes: 3 additions & 0 deletions android-example/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.gradle
.idea
build
local.properties
4 changes: 2 additions & 2 deletions android-example/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ android {

applicationId = "org.rewedigital.katana.android.example"
versionCode = 1
versionName = "1.2.8"
versionName = "1.3.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}

dependencies {
implementation("org.rewedigital.katana:katana-android:1.2.8")
implementation("org.rewedigital.katana:katana-android:1.3.0")
implementation("androidx.appcompat:appcompat:1.0.2")
implementation("androidx.constraintlayout:constraintlayout:1.1.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,21 @@ package org.rewedigital.katana.android.example.main

import androidx.test.espresso.idling.CountingIdlingResource
import org.rewedigital.katana.android.example.remote.*
import org.rewedigital.katana.bind
import org.rewedigital.katana.createModule
import org.rewedigital.katana.get
import org.rewedigital.katana.singleton
import org.rewedigital.katana.dsl.compact.singleton
import org.rewedigital.katana.dsl.get

val testSuccessApiMockModule = createModule("testSuccessApiMockModule") {

bind<JsonPlaceholderApi> {
singleton {
JsonPlaceholderApiSuccessMock()
}
singleton<JsonPlaceholderApi> {
JsonPlaceholderApiSuccessMock()
}
}

val testErrorApiMockModule = createModule("testErrorApiMockModule") {

bind<JsonPlaceholderApi> {
singleton {
JsonPlaceholderApiErrorMock()
}
singleton<JsonPlaceholderApi> {
JsonPlaceholderApiErrorMock()
}
}

Expand All @@ -31,16 +26,14 @@ const val TEST_IDLING_RESOURCE = "TEST_IDLING_RESOURCE"
fun createTestRepositoryModule(repositoryIdlingResource: CountingIdlingResource) =
createModule("testRepositoryModule") {

bind<CountingIdlingResource>(TEST_IDLING_RESOURCE) { singleton { repositoryIdlingResource } }
singleton(name = TEST_IDLING_RESOURCE) { repositoryIdlingResource }

bind<JsonPlaceholderRepository>(TEST_REPO) { singleton { JsonPlaceholderRepositoryImpl(get()) } }
singleton<JsonPlaceholderRepository>(name = TEST_REPO) { JsonPlaceholderRepositoryImpl(get()) }

bind<JsonPlaceholderRepository> {
singleton {
TestJsonPlaceholderRepository(
get(TEST_REPO),
get(TEST_IDLING_RESOURCE)
)
}
singleton<JsonPlaceholderRepository> {
TestJsonPlaceholderRepository(
get(TEST_REPO),
get(TEST_IDLING_RESOURCE)
)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package org.rewedigital.katana.android.example.fragment

import org.rewedigital.katana.bind
import org.rewedigital.katana.createModule
import org.rewedigital.katana.factory
import org.rewedigital.katana.dsl.compact.factory

const val FRAGMENT_DEPENDENCY1 = "FRAGMENT_DEPENDENCY1"

val firstFragmentModule = createModule {

bind<String>(FRAGMENT_DEPENDENCY1) { factory { "FRAGMENT_DEPENDENCY1" } }
factory(name = FRAGMENT_DEPENDENCY1) { "FRAGMENT_DEPENDENCY1" }
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package org.rewedigital.katana.android.example.fragment

import org.rewedigital.katana.bind
import org.rewedigital.katana.createModule
import org.rewedigital.katana.factory
import org.rewedigital.katana.dsl.compact.factory

const val SOME_DEPENDENCY = "SOME_DEPENDENCY"

val fragmentActivityModule = createModule {

bind<String>(SOME_DEPENDENCY) { factory { "SOME_DEPENDENCY" } }
factory(name = SOME_DEPENDENCY) { "SOME_DEPENDENCY" }
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package org.rewedigital.katana.android.example.fragment

import org.rewedigital.katana.android.example.fragment.inject.Container
import org.rewedigital.katana.bind
import org.rewedigital.katana.createModule
import org.rewedigital.katana.factory
import org.rewedigital.katana.get
import org.rewedigital.katana.dsl.compact.factory
import org.rewedigital.katana.dsl.get

const val FRAGMENT_DEPENDENCY2 = "FRAGMENT_DEPENDENCY2"

val secondFragmentModule = createModule {

bind<String>(FRAGMENT_DEPENDENCY2) { factory { "FRAGMENT_DEPENDENCY2" } }
factory(name = FRAGMENT_DEPENDENCY2) { "FRAGMENT_DEPENDENCY2" }

bind<Container> { factory { Container(get(SOME_DEPENDENCY), get(FRAGMENT_DEPENDENCY2)) } }
factory { Container(get(SOME_DEPENDENCY), get(FRAGMENT_DEPENDENCY2)) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package org.rewedigital.katana.android.example.inject
import android.content.Context
import android.content.res.Resources
import org.rewedigital.katana.android.modules.APPLICATION_CONTEXT
import org.rewedigital.katana.bind
import org.rewedigital.katana.createModule
import org.rewedigital.katana.factory
import org.rewedigital.katana.get
import org.rewedigital.katana.dsl.compact.factory
import org.rewedigital.katana.dsl.get

/**
* This module may provide Android specific classes like [Resources],
Expand All @@ -16,5 +15,5 @@ import org.rewedigital.katana.get
*/
val androidModule = createModule {

bind<Resources> { factory { get<Context>(APPLICATION_CONTEXT).resources } }
factory { get<Context>(APPLICATION_CONTEXT).resources }
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import org.rewedigital.katana.android.example.main.view.MainActivity
import org.rewedigital.katana.android.example.main.view.MainView
import org.rewedigital.katana.android.modules.ACTIVITY
import org.rewedigital.katana.android.modules.ACTIVITY_CONTEXT
import org.rewedigital.katana.bind
import org.rewedigital.katana.createModule
import org.rewedigital.katana.get
import org.rewedigital.katana.singleton
import org.rewedigital.katana.dsl.compact.singleton
import org.rewedigital.katana.dsl.get

/**
* This module demonstrates how the current [Context] can be injected safely.
Expand All @@ -31,15 +30,15 @@ import org.rewedigital.katana.singleton
*/
fun createMainModule(activity: MainActivity) = createModule {

bind<ButtonMapper> { singleton { ButtonMapperImpl(get(ACTIVITY_CONTEXT)) } }
singleton<ButtonMapper> { ButtonMapperImpl(get(ACTIVITY_CONTEXT)) }

bind<ButtonRepository> { singleton { ButtonRepositoryImpl() } }
singleton<ButtonRepository> { ButtonRepositoryImpl() }

bind<MainView> { singleton { activity } }
singleton<MainView> { activity }

bind<MainPresenter> { singleton { MainPresenterImpl(get(), get(), get()) } }
singleton<MainPresenter> { MainPresenterImpl(get(), get(), get()) }

bind<MainInteractor> { singleton { MainInteractorImpl(get(), get(), get()) } }
singleton<MainInteractor> { MainInteractorImpl(get(), get(), get()) }

bind<MainNavigator> { singleton { MainNavigatorImpl(get(ACTIVITY)) } }
singleton<MainNavigator> { MainNavigatorImpl(get(ACTIVITY)) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,42 @@ package org.rewedigital.katana.android.example.remote
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import org.rewedigital.katana.*
import org.rewedigital.katana.createModule
import org.rewedigital.katana.dsl.compact.factory
import org.rewedigital.katana.dsl.compact.singleton
import org.rewedigital.katana.dsl.get
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory

val moshiModule = createModule("moshiModule") {

bind<Moshi> {
singleton {
Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
}
singleton {
Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
}
}

val retrofitModule = createModule("retrofitModule") {

bind<Retrofit.Builder> {
factory {
Retrofit.Builder()
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.addConverterFactory(MoshiConverterFactory.create(get()))
}
factory {
Retrofit.Builder()
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.addConverterFactory(MoshiConverterFactory.create(get()))
}
}

val apiModule = createModule("apiModule") {

bind<JsonPlaceholderApi> {
singleton {
get<Retrofit.Builder>()
.baseUrl("https://jsonplaceholder.typicode.com/")
.build()
.create(JsonPlaceholderApi::class.java)
}
singleton {
get<Retrofit.Builder>()
.baseUrl("https://jsonplaceholder.typicode.com/")
.build()
.create(JsonPlaceholderApi::class.java)
}
}

val repositoryModule = createModule("repositoryModule") {

bind<JsonPlaceholderRepository> { singleton { JsonPlaceholderRepositoryImpl(get()) } }
singleton<JsonPlaceholderRepository> { JsonPlaceholderRepositoryImpl(get()) }
}
5 changes: 5 additions & 0 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ android {
targetSdkVersion(Android.targetSdkVersion)
}

sourceSets {
getByName("main").java.srcDirs("src/main/kotlin")
getByName("test").java.srcDirs("src/test/kotlin")
}

buildTypes {
getByName("release") {
isMinifyEnabled = true
Expand Down
Loading

0 comments on commit d3b76ab

Please sign in to comment.