Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Upcoming SlideShare
What to Upload to SlideShare
What to Upload to SlideShare
Loading in …3
×
1 of 65

Koin Quickstart

1

Share

Download to read offline

Slides from a talk and live-coding session about Koin, a pragmatic and lightweight Dependency Injection framework for Kotlin. This talk was given at Auckland Android Community on Dec 5.
https://www.meetup.com/Android-Meetup/events/256734688/

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Koin Quickstart

  1. 1. Koin Quickstart Matt Clarke - Auckland Android Community - Dec 2018
  2. 2. What is Koin?
  3. 3. What is Koin? • From insert-koin.io:
  4. 4. What is Koin? • From insert-koin.io: • A pragmatic lightweight dependency injection framework for Kotlin developers.
  5. 5. What is Koin? • From insert-koin.io: • A pragmatic lightweight dependency injection framework for Kotlin developers. • Written in pure Kotlin, using functional resolution only: no proxy, no code generation, no reflection.
  6. 6. What is Koin? • From insert-koin.io: • A pragmatic lightweight dependency injection framework for Kotlin developers. • Written in pure Kotlin, using functional resolution only: no proxy, no code generation, no reflection. • Koin is a DSL, a light container and a pragmatic API
  7. 7. What is Koin?
  8. 8. What is Koin? public class Person { private String name; private int age = 0; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; if (name != null ? !name.equals(person.name) : person.name != null) return false; if (age != 0 ? age != person.age : person.age != 0) return false; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; } @Override public String toString() { return "Person{" + "name='" + name + ''' + ", age='" + age + ''' + '}'; } }
  9. 9. What is Koin? data class Person(var name: String, var age: Int)
  10. 10. What is Koin? data class Person(var name: String, var age: Int) i.e. “Koin is to Dagger as Kotlin is to Java”
  11. 11. Live (mob) coding
  12. 12. Deep(er) dive: How does any of this work?
  13. 13. Deep(er) dive: How does any of this work? val postModule = module { single { PostPresenter(get()) } }
  14. 14. Deep(er) dive: How does any of this work? val postModule = module { single { PostPresenter(get()) } }
  15. 15. How does any of this work?
  16. 16. How does any of this work? /** * Create a Module * Gather definitions * @param path : Path of the module * @param createOnStart : module definitions will be tagged as `createOnStart` * @param override : allow all definitions from module to override definitions */ fun module( path: String = Path.ROOT, createOnStart: Boolean = false, override: Boolean = false, definition: ModuleDefinition.() -> Unit ): Module = { koinContext -> ModuleDefinition(path, createOnStart, override, koinContext).apply(definition) } org/koin/dsl/module/Module.kt
  17. 17. How does any of this work? /** * Create a Module * Gather definitions * @param path : Path of the module * @param createOnStart : module definitions will be tagged as `createOnStart` * @param override : allow all definitions from module to override definitions */ fun module( path: String = Path.ROOT, createOnStart: Boolean = false, override: Boolean = false, definition: ModuleDefinition.() -> Unit ): Module = { koinContext -> ModuleDefinition(path, createOnStart, override, koinContext).apply(definition) } org/koin/dsl/module/Module.kt
  18. 18. How does any of this work? /** * Create a Module * Gather definitions * @param path : Path of the module * @param createOnStart : module definitions will be tagged as `createOnStart` * @param override : allow all definitions from module to override definitions */ fun module( path: String = Path.ROOT, createOnStart: Boolean = false, override: Boolean = false, definition: ModuleDefinition.() -> Unit ): Module = { koinContext -> ModuleDefinition(path, createOnStart, override, koinContext).apply(definition) } org/koin/dsl/module/Module.kt
  19. 19. How does any of this work?
  20. 20. How does any of this work? kotlinlang.org/docs/reference/lambdas.html
  21. 21. How does any of this work?
  22. 22. How does any of this work? val postModule = module { single { PostPresenter(get()) } }
  23. 23. How does any of this work? val postModule: Module = module(definition = { single { PostPresenter(get()) } })
  24. 24. How does any of this work? val postModule: Module = module(definition = { single { PostPresenter(get()) } })
  25. 25. How does any of this work?
  26. 26. How does any of this work? /** * Create a Module * Gather definitions * @param path : Path of the module * @param createOnStart : module definitions will be tagged as `createOnStart` * @param override : allow all definitions from module to override definitions */ fun module( path: String = Path.ROOT, createOnStart: Boolean = false, override: Boolean = false, definition: ModuleDefinition.() -> Unit ): Module = { koinContext -> ModuleDefinition(path, createOnStart, override, koinContext).apply(definition) } org/koin/dsl/module/Module.kt
  27. 27. How does any of this work? /** * Create a Module * Gather definitions * @param path : Path of the module * @param createOnStart : module definitions will be tagged as `createOnStart` * @param override : allow all definitions from module to override definitions */ fun module( path: String = Path.ROOT, createOnStart: Boolean = false, override: Boolean = false, definition: ModuleDefinition.() -> Unit ): Module = { koinContext -> ModuleDefinition(path, createOnStart, override, koinContext).apply(definition) } org/koin/dsl/module/Module.kt
  28. 28. How does any of this work? val postModule: Module = module(definition = { single { PostPresenter(get()) } })
  29. 29. How does any of this work? val postModule: Module = module(definition = { this.single { PostPresenter(get()) } })
  30. 30. How does any of this work? val postModule: Module = module(definition = { this.single { PostPresenter(get()) } })
  31. 31. How does any of this work?
  32. 32. How does any of this work? /** * Provide a single instance definition * (unique instance) * * @param name * @param createOnStart - need to be created at start * @param override - allow definition override * @param definition */ inline fun <reified T : Any> single( name: String = "", createOnStart: Boolean = false, override: Boolean = false, noinline definition: Definition<T> ): BeanDefinition<T> { return provide(name, createOnStart, override, Kind.Single, definition) } org/koin/dsl/context/ModuleDefinition.kt
  33. 33. Type-Safe Builders
  34. 34. Type-Safe Builders https://kotlinlang.org/docs/reference/type-safe-builders.html
  35. 35. Type-Safe Builders
  36. 36. Type-Safe Builders
  37. 37. What about this?
  38. 38. What about this? /** * Activity displaying the list of posts */ class PostActivity : AppCompatActivity(), PostView { private val presenter: PostPresenter by inject() // ...
  39. 39. What about this? /** * Activity displaying the list of posts */ class PostActivity : AppCompatActivity(), PostView { private val presenter: PostPresenter by inject() // ...
  40. 40. No magic
  41. 41. No magic • Koin takes full advantage of Kotlin’s adv. language features
  42. 42. No magic • Koin takes full advantage of Kotlin’s adv. language features • E.g. reified generics, lambdas with receivers, type inference
  43. 43. No magic • Koin takes full advantage of Kotlin’s adv. language features • E.g. reified generics, lambdas with receivers, type inference • Less opaque/magical than annotation processing pipeline for application developers
  44. 44. Testability?
  45. 45. Testability? // Just tag your class with KoinTest to unlock your testing power class SimpleTest : KoinTest { // lazy inject BusinessService into property val service : BusinessService by inject() @Test fun myTest() { // You can start your Koin configuration startKoin(myModules) // or directly get any instance val service : BusinessService = get() // Don't forget to close it at the end closeKoin() } }
  46. 46. What about Scopes?
  47. 47. What about Scopes? val appModule = module { // single instance of HelloRepository single<HelloRepository> { HelloRepositoryImpl() } // Scoped MyScopePresenter instance scope("session") { MyScopePresenter(get())} }
  48. 48. What about Scopes?
  49. 49. What about Scopes? class MyScopeActivity : AppCompatActivity() { // inject MyScopePresenter from "session" scope val scopePresenter: MyScopePresenter by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_simple) // bind "session" scope to component lifecycle bindScope(getOrCreateScope("session")) //... } }
  50. 50. Koin vs. Dagger overview
  51. 51. Koin vs. Dagger overview • Koin pros:
  52. 52. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn
  53. 53. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn • No annotation processing/code gen. Just language features
  54. 54. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn • No annotation processing/code gen. Just language features • Straightforward Android integration
  55. 55. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn • No annotation processing/code gen. Just language features • Straightforward Android integration • Nice, simple documentation
  56. 56. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn • No annotation processing/code gen. Just language features • Straightforward Android integration • Nice, simple documentation • Build speed (?)
  57. 57. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn • No annotation processing/code gen. Just language features • Straightforward Android integration • Nice, simple documentation • Build speed (?) • Koin cons:
  58. 58. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn • No annotation processing/code gen. Just language features • Straightforward Android integration • Nice, simple documentation • Build speed (?) • Koin cons: • Runtime dependency resolution (though minimal overhead)
  59. 59. Koin vs. Dagger overview • Koin pros: • Less boilerplate. Less arcane, easy to learn • No annotation processing/code gen. Just language features • Straightforward Android integration • Nice, simple documentation • Build speed (?) • Koin cons: • Runtime dependency resolution (though minimal overhead) • Newer, relatively unproven (compared to Dagger)
  60. 60. Is it Production-Ready?
  61. 61. Is it Production-Ready? • Research didn’t turn up much, but…
  62. 62. Is it Production-Ready? • Research didn’t turn up much, but… • Reached v1.0 in Sep (FWIW)
  63. 63. Is it Production-Ready? • Research didn’t turn up much, but… • Reached v1.0 in Sep (FWIW) • The author uses it in several production apps…
  64. 64. Is it Production-Ready? • Research didn’t turn up much, but… • Reached v1.0 in Sep (FWIW) • The author uses it in several production apps… • Workable team uses it prod, details here: https:// medium.com/@charbgr/bye-bye-dagger-1494118dcd41
  65. 65. Thanks!
 Questions/thoughts/ comments? Twitter: @kiwiandroiddev Email: kiwiandroiddev@gmail.com

×