4. public class Twitter {
public void getFeeds() {
TwitterApi api = new TwitterApi();
api.getFeeds();
}
}
public class TwitterApi {
public void getFeeds () {
HttpClient httpClient = new HttpClient();
httpClient.connect("http://xxx.com")
}
}
5. public class Twitter {
public void getFeeds() {
TwitterApi api = new TwitterApi();
api.getFeeds();
}
}
public class TwitterApi {
public void getFeeds () {
HttpClient httpClient = new HttpClient();
httpClient.connect("http://xxx.com")
}
}
6. What’s the problem now?
● New is evil
● High coupling
● Hard to replace
● Hard to test
8. How to Inject Object?
● Constructor Injection
● Method Injection
● Field Injection
9. public class Twitter {
public void getFeeds() {
TwitterApi api = new TwitterApi();
api.getFeeds();
}
}
public class TwitterApi {
public void getFeeds () {
HttpClient httpClient = new HttpClient();
httpClient.connect("http://xxx.com")
}
}
10. public class Twitter {
public void getFeeds(TwitterApi api) {
api.getFeeds();
}
}
public class TwitterApi {
HttpClient httpClient;
public TwitterApi(HttpClient httpClient) {
this.httpClient = httpClient;
}
}
11. What’s the problem now?
● Hard to use
● Manage dependency graph is a mess
● Dagger is the rescue
27. koin
● Service locator by Kotlin DSL
● No code generation
● No reflection
● No compile time overhead
● Pure Kotlin
● https://github.com/InsertKoinIO/koin
28. Service locator
The service locator pattern is a design pattern
used in software development to encapsulate the
processes involved in obtaining a service with a
strong abstraction layer.
30. Kotlin DSL
● Function literals with receiver
● Describe data structure
● Like Anko, ktor
31. // HTML DSL
val result =
html {
head {
title {+"XML encoding with Kotlin"}
}
body {
h1 {+"XML encoding with Kotlin"}
p {+"this format can be used"}
a(href = "http://kotlinlang.org") {+"Kotlin"}
}
}
32. fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
fun body(init: Body.() -> Unit) : Body {
val body = Body()
body.init()
return body
}
33. koin DSL
● Module - create a Koin Module
● Factory - provide a factory bean definition
● Single - provide a singleton bean definition
(also aliased as bean)
● Get - resolve a component dependency
34. // gradle install
dependencies {
// Koin for Android
compile 'org.koin:koin-android:1.0.2'
// or Koin for Lifecycle scoping
compile 'org.koin:koin-android-scope:1.0.2'
// or Koin for Android Architecture ViewModel
compile 'org.koin:koin-android-viewmodel:1.0.2'
}
35. // Object class
class Bee
class Honey(var bee: Bee)
class Lemon
class HoneyLemonade(var honey: Honey,
var lemon: Lemon)
36. class MyApplication : Application() {
override fun onCreate(){
super.onCreate()
// start Koin!
startKoin(this, listOf(myModule))
}
}
val myModule = module {
single { Bee() }
single { Honey(get()) }
single { Lemon() }
single { HoneyLemonade(get(), get()) }
}
37. // How get() work? reified
inline fun <reified T : Any> get(
name: String = "",
scopeId: String? = null,
noinline parameters: ParameterDefinition = ...
): T {
val scope: Scope? = scopeId?.let {
koinContext.getScope(scopeId)
}
return koinContext.get(name, scope, parameters)
}
38. reified function
● Work with inline
● Can access actual type T
● After compile T will replace with actual type
39. class MyActivity() : AppCompatActivity() {
val drink : HoneyLemonade by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val drink : HoneyLemonade = get()
}
}
40. // How inject(), get() work?
inline fun <reified T : Any> ComponentCallbacks.inject(
name: String = "",
scope: Scope? = null,
noinline parameters: ParameterDefinition = ...
) = lazy { get<T>(name, scope, parameters) }
inline fun <reified T : Any> ComponentCallbacks.get(
name: String = "",
scope: Scope? = null,
noinline parameters: ParameterDefinition = ...
): T = getKoin().get(name, scope, parameters)
// What is ComponentCallbacks btw?