SlideShare a Scribd company logo
Kiev 2018
Absolute Mobile Fest
Kirill Rozov
Android Developer
Kiev 2018Insert Koin
Dependency Injection
Kiev 2018Insert Koin
Inversion of Control (IoC) is a design
principle in which custom-written portions
of a computer program receive the flow of
control from a generic framework
wikipedia.org/wiki/Inversion_of_control
Kiev 2018Insert Koin
Inversion of Control
CLIENT
CLIENT
CLIENT
DEPENDENCY 1
DEPENDENCY 2
DEPENDENCY 3
DEPENDENCY 4
Kiev 2018Insert Koin
Inversion of Control
DEPENDENCY 1
DEPENDENCY 2
DEPENDENCY 3
DEPENDENCY 4
IoC CONTAINER
CLIENT
CLIENT
CLIENT
Kiev 2018Insert Koin
Inversion of Control
DEPENDENCY 1
DEPENDENCY 2
DEPENDENCY 3
DEPENDENCY 4
IoC CONTAINER
CLIENT
CLIENT
CLIENT
Kiev 2018Insert Koin
Popular DI
• Guice
• Spring DI
• Square Dagger
• Google Dagger 2
• Java EE CDI
• PicoContainer
• Kodein
• Koin
Kiev 2018Insert Koin
insert-Koin.io
Kiev 2018Insert Koin
Kiev 2018Insert Koin
Sample
val sampleModule = applicationContext {
bean { ComponentA() }
}
Kiev 2018Insert Koin
Sample
val sampleModule = applicationContext {
bean { ComponentA() }
}
Kiev 2018Insert Koin
Sample
val sampleModule = applicationContext {
bean { ComponentA() }
}
class Application : KoinComponent {
val component by inject<ComponentA>()
}
Kiev 2018Insert Koin
Sample
val sampleModule = applicationContext {
bean { ComponentA() }
}
class Application : KoinComponent {
val component by inject<ComponentA>()
}
Kiev 2018Insert Koin
Sample
val sampleModule = applicationContext {
bean { ComponentA() }
}
class Application : KoinComponent {
val component by inject<ComponentA>()
}
fun main(vararg args: String) {
startKoin(listOf(sampleModule))
}
Kiev 2018Insert Koin
Init
class SampleApplication : Application() {
override fun onCreate() {
startKoin(this, listOf(sampleModule))
}
}
fun main(vararg args: String) {
start(listOf(sampleModule)) { … }
}
fun main(vararg args: String) {
startKoin(listOf(sampleModule))
}
Kiev 2018Insert Koin
KoinComponent
fun <T> KoinComponent.inject(name: String) : Lazy<T>
fun <T> KoinComponent.inject(name: String, paras: Parameters) : Lazy<T>
fun <T> KoinComponent.property(key: String) : T
fun <T> KoinComponent.property(key: String, defaultValue: T) : T
fun <T> KoinComponent.get(name: String) : T
fun <T> KoinComponent.get(name: String, params: Parameters) : T
fun KoinComponent.setProperty(key: String, value: Any)
fun KoinComponent.releaseContext(name: String)
fun KoinComponent.releaseProperties(vararg keys: String)
interface KoinComponent
Kiev 2018Insert Koin
KoinComponent
fun <T> KoinComponent.inject(name: String) : Lazy<T>
fun <T> KoinComponent.inject(name: String, paras: Parameters) : Lazy<T>
fun <T> KoinComponent.property(key: String) : T
fun <T> KoinComponent.property(key: String, defaultValue: T) : T
fun <T> KoinComponent.get(name: String) : T
fun <T> KoinComponent.get(name: String, params: Parameters) : T
fun KoinComponent.setProperty(key: String, value: Any)
fun KoinComponent.releaseContext(name: String)
fun KoinComponent.releaseProperties(vararg keys: String)
Kiev 2018Insert Koin
KoinComponent
fun <T> ComponentCallbacks.inject(name: String) : Lazy<T>
fun <T> ComponentCallbacks.inject(name: String, paras: Parameters) : Lazy<T>
fun <T> ComponentCallbacks.property(key: String) : T
fun <T> ComponentCallbacks.property(key: String, defaultValue: T) : T
fun <T> ComponentCallbacks.get(name: String) : T
fun <T> ComponentCallbacks.get(name: String, params: Parameters) : T
fun ComponentCallbacks.setProperty(key: String, value: Any)
fun ComponentCallbacks.releaseContext(name: String)
fun ComponentCallbacks.releaseProperties(vararg keys: String)
Kiev 2018Insert Koin
Provide dependencies
applicationContext {
bean { ComponentA() }
factory { ComponentB() }
}
Kiev 2018Insert Koin
Provide dependencies
applicationContext {
bean { ComponentA() }
factory { ComponentB() }
}
Kiev 2018Insert Koin
Provide dependencies
class ComponentA(c : ComponentB)
Kiev 2018Insert Koin
Provide dependencies
applicationContext {
bean { ComponentB() }
bean { ComponentA(get<ComponentB>()) }
}
class ComponentA(c : ComponentB)
Kiev 2018Insert Koin
Named dependencies
applicationContext {
bean { ComponentB(…) }
bean { ComponentB(…) }
}
Kiev 2018Insert Koin
Named dependencies
applicationContext {
bean(“debug”) { ComponentB(…) }
bean(“prod”) { ComponentB(…) }
}
Kiev 2018Insert Koin
Named dependencies
applicationContext {
bean(“debug”) { ComponentB(…) }
bean(“prod”) { ComponentB(…) }
bean { ComponentA(get(“debug”)) }
}
Kiev 2018Insert Koin
Named dependencies
applicationContext {
bean(“debug”) { ComponentB() }
bean(“prod”) { ComponentB() }
bean { ComponentA(get(“debug”)) }
}
class Application : KoinComponent {
val componentProd by inject<ComponentB>(“prod”)
val componentDebug by inject<ComponentB>(“debug”)
}
Kiev 2018Insert Koin
Type binding
applicationContext {
bean { ComponentImpl() }
bean { ComponentImpl() as Component }
bean { ComponentImpl() } bind Component::class
}
Kiev 2018Insert Koin
Dependency Parameters
Kiev 2018Insert Koin
Properties
class RestService(url: String)
Kiev 2018Insert Koin
Properties
applicationContext {
bean { RestService(getProperty(“url”)) }
}
class RestService(url: String)
Kiev 2018Insert Koin
Properties
applicationContext {
bean { RestService(getProperty(“url”)) }
}
class RestService(url: String)
applicationContext {
bean { RestService(getProperty(“url”, “http://localhost”)) }
}
Kiev 2018Insert Koin
Properties
applicationContext {
bean { RestService(getProperty(“url”)) }
}
class RestService(url: String)
applicationContext {
bean { RestService(getProperty(“url”, “http://localhost”)) }
}
val key1Property: String by property(“key1”)
Kiev 2018Insert Koin
Properties
startKoin(properties: Map<String, Any> = mapOf(“key” to 1))
Kiev 2018Insert Koin
Properties Sources
• koin.properties in JAR resources
• koin.properties in assets
• Environment properties
Kiev 2018Insert Koin
Environment variables
startKoin(useEnvironmentProperties = true)
// Get user name from properties
val key1Property: String by property(“USER”)
Kiev 2018Insert Koin
Problem
class NewsDetailPresenter(newsId : String)
Kiev 2018Insert Koin
Parameters
val presenter: NewsDetailPresenter
by inject { mapOf(NEWS_ID to "sample") }
Kiev 2018Insert Koin
Parameters
applicationContext {
factory { params: ParametersProvider ->
NewsDetailsPresenter(params[NEWS_ID])
}
}
val presenter: NewsDetailPresenter
by inject { mapOf(NEWS_ID to "sample") }
Kiev 2018Insert Koin
Parameters
applicationContext {
factory { params: ParametersProvider ->
NewsDetailsPresenter(params[NEWS_ID])
}
}
val presenter: NewsDetailPresenter
by inject { mapOf(NEWS_ID to "sample") }
interface ParametersProvider {
operator fun <T> get(key: String): T
fun <T> getOrNull(key: String): T?
}
Kiev 2018Insert Koin
Contexts
Kiev 2018Insert Koin
Contexts
applicationContext {
context("main") {
bean { ComponentA() }
bean { ComponentB() }
}
}
Kiev 2018Insert Koin
Contexts
applicationContext {
context("main") {
bean { ComponentA() }
bean { ComponentB() }
}
}
class MainActivity : Activity() {
override fun onStop() {
releaseContext("main")
}
}
Kiev 2018Insert Koin
Context isolation
applicationContext {
context("A") {
bean { ComponentA() }
context("B") {
bean { ComponentB() }
}
}
context("C") {
bean { ComponentС() }
}
}
Kiev 2018Insert Koin
Context isolation
applicationContext {
context("A") {
bean { ComponentA() }
context("B") {
bean { ComponentB() }
}
}
context("C") {
bean { ComponentС() }
}
}
Kiev 2018Insert Koin
Context isolation
applicationContext {
context("A") {
bean { ComponentA() }
context("B") {
bean { ComponentB() }
}
}
context("C") {
bean { ComponentС() }
}
}
Kiev 2018Insert Koin
Context isolation
applicationContext {
context("A") {
bean { ComponentA() }
context("B") {
bean { ComponentB() }
}
}
context("C") {
bean { ComponentС() }
}
}
Kiev 2018Insert Koin
Logging
Kiev 2018Insert Koin
class Presenter(repository: Repository)
class Repository(dateSource: DateSource)
interface DateSource
class DebugDataSource() : DateSource
Kiev 2018Insert Koin
applicationContext {
factory { Presenter(get()) }
bean { Repository(get()) }
bean { DebugDataSource() } bind DateSource::class
}
class Presenter(repository: Repository)
class Repository(dateSource: DateSource)
interface DateSource
class DebugDataSource() : DateSource
Kiev 2018Insert Koin
applicationContext {
factory { Presenter(get()) }
bean { Repository(get()) }
bean { DebugDataSource() } bind DateSource::class
}
get<Presenter>()
get<Presenter>()
class Presenter(repository: Repository)
class Repository(dateSource: DateSource)
interface DateSource
class DebugDataSource() : DateSource
Kiev 2018Insert Koin
applicationContext {
factory { Presenter(get()) }
bean { Repository(get()) }
bean { DebugDataSource() } bind DateSource::class
}
get<Presenter>()
get<Presenter>()
(KOIN) :: Resolve [Presenter] ~ Factory[class=Presenter]
(KOIN) :: Resolve [Repository] ~ Bean[class=Repository]
(KOIN) :: Resolve [Datasource] ~ Bean[class=DebugDatasource, binds~(Datasource)]
(KOIN) :: (*) Created
(KOIN) :: (*) Created
(KOIN) :: (*) Created
(KOIN) :: Resolve [Repository] ~ Factory[class=Repository]
(KOIN) :: Resolve [DebugDatasource] ~ Bean[class=DebugDatasource, binds~(Datasource)]
(KOIN) :: (*) Created
class Presenter(repository: Repository)
class Repository(dateSource: DateSource)
interface DateSource
class DebugDataSource() : DateSource
Kiev 2018Insert Koin
Missing dependency
applicationContext {
bean { ComponentA(get()) }
bean { ComponentB(get()) }
}
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentA)
get<ComponentC>()
Kiev 2018Insert Koin
Missing dependency
applicationContext {
bean { ComponentA(get()) }
bean { ComponentB(get()) }
}
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentA)
org.koin.error.DependencyResolutionException:
No definition found for ComponentC - Check your definitions and contexts visibility
get<ComponentC>()
Kiev 2018Insert Koin
Cyclic dependencies
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentA)
Kiev 2018Insert Koin
Cyclic dependencies
applicationContext {
bean { ComponentA(get()) }
bean { ComponentB(get()) }
}
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentA)
Kiev 2018Insert Koin
Cyclic dependencies
get<ComponentA>()
applicationContext {
bean { ComponentA(get()) }
bean { ComponentB(get()) }
}
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentA)
Kiev 2018Insert Koin
Cyclic dependencies
org.koin.error.BeanInstanceCreationException: Can't create bean Bean[class=ComponentA] due to error :
BeanInstanceCreationException: Can't create bean Bean[class=ComponentB] due to error :
BeanInstanceCreationException: Can't create bean Bean[class=ComponentA] due to error :
DependencyResolutionException: Cyclic dependency detected while resolving class ComponentA
applicationContext {
bean { ComponentA(get()) }
bean { ComponentB(get()) }
}
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentA)
get<ComponentA>()
Kiev 2018Insert Koin
Tests
Kiev 2018Insert Koin
Tests
class SampleTest : KoinTest {
val presenter : MyPresenter by inject()
val repository : Repository by inject()
@Before
fun before(){
startKoin(listOf(myModule))
}
@Test
fun testSayHello() {
val hello = repository.giveHello()
assertEquals(hello, presenter.sayHello())
}
@After
fun after(){
closeKoin()
}
}
Kiev 2018Insert Koin
Tests
class SampleTest : KoinTest {
val presenter : MyPresenter by inject()
val repository : Repository by inject()
@Before
fun before(){
startKoin(listOf(myModule))
}
@Test
fun testSayHello() {
val hello = repository.giveHello()
assertEquals(hello, presenter.sayHello())
}
@After
fun after(){
closeKoin()
}
}
Kiev 2018Insert Koin
Tests
class SampleTest : KoinTest {
val presenter : MyPresenter by inject()
val repository : Repository by inject()
@Before
fun before(){
startKoin(listOf(myModule))
}
@Test
fun testSayHello() {
val hello = repository.giveHello()
assertEquals(hello, presenter.sayHello())
}
@After
fun after(){
closeKoin()
}
}
Kiev 2018Insert Koin
Tests
class SampleTest : KoinTest {
val presenter : MyPresenter by inject()
val repository : Repository by inject()
@Before
fun before(){
startKoin(listOf(myModule))
}
@Test
fun testSayHello() {
val hello = repository.giveHello()
assertEquals(hello, presenter.sayHello())
}
@After
fun after(){
closeKoin()
}
}
Kiev 2018Insert Koin
Graph validation
Kiev 2018Insert Koin
Graph validation
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentC)
class ComponentC()
Kiev 2018Insert Koin
Graph validation
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentC)
class ComponentC()
val sampleModule = applicationContext {
bean { ComponentA(get()) }
factory { ComponentB(get()) }
}
Kiev 2018Insert Koin
Graph validation
class ComponentA(component: ComponentB)
class ComponentB(component: ComponentC)
class ComponentC()
val sampleModule = applicationContext {
bean { ComponentA(get()) }
factory { ComponentB(get()) }
}
class DryRunTest : KoinTest {
@Test
fun dryRunTest() {
startKoin(listOf(sampleModule))
dryRun()
}
}
Kiev 2018Insert Koin
Android Arch Components
Kiev 2018Insert Koin
Default Way
class ListFragment : Fragment() {
val listViewModel =
ViewModelProviders.of(this).get(ListViewModel::class.java)
}
Kiev 2018Insert Koin
Simpler with Kotlin
class ListFragment : Fragment() {
val listViewModel = getViewModel<ListViewModel>()
}
inline fun <reified VM : ViewModel> Fragment.getViewModel():VM {
return viewModelProvider.get(VM::class.java)
}
Kiev 2018Insert Koin
ViewModel with arguments
class DetailViewModel(id: String) : ViewModel()
Kiev 2018Insert Koin
ViewModel with arguments
class DetailViewModel(id: String) : ViewModel()
class DetailFactory(val id: String) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass == DetailViewModel::class.java) {
return DetailViewModel(id) as T
}
error("Can't create ViewModel for class='$modelClass'")
}
}
Kiev 2018Insert Koin
ViewModel with arguments
class DetailViewModel(id: String) : ViewModel()
class DetailFactory(val id: String) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass == DetailViewModel::class.java) {
return DetailViewModel(id) as T
}
error("Can't create ViewModel for class='$modelClass'")
}
}
class ListFragment : Fragment() {
val listViewModel = provideViewModel<DetailViewModel>(DetailFactory(id))
}
Kiev 2018Insert Koin
Koin Way
applicationContext {
viewModel { params -> DetailViewModel(params["id"]) }
}
Kiev 2018Insert Koin
Koin Way
applicationContext {
viewModel { params -> DetailViewModel(params["id"]) }
}
class ListFragment : Fragment() {
val listViewModel
by viewModel<ListViewModel> { mapOf("id" to "sample") }
}
Kiev 2018Insert Koin
Koin vs Dagger 2
Kiev 2018Insert Koin
What missed from Dagger 2?
• Compile time validation
• Features
• Multibindings
• Async Injection
• Reusable scope
Kiev 2018Insert Koin
Why use Koin?
• Dagger 2 is too complex for start with DI
• No need Dagger 2 advanced features
• Single place of dependencies declaration
• DSL is amazing for dependencies declaration
• Support Kotlin Multiplatform projects
• Faster build time
• Pure Kotlin code
Kiev 2018Insert Koin
Thanks insert-Koin.io
kiryl.rozau@apalon.com
krlrozov

More Related Content

What's hot

Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
Jorge Ortiz
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
Christoffer Noring
 
What's new in c# 10
What's new in c# 10What's new in c# 10
What's new in c# 10
Moaid Hathot
 
Generating cross platform .NET based azure IoTdevice
Generating cross platform .NET based azure IoTdeviceGenerating cross platform .NET based azure IoTdevice
Generating cross platform .NET based azure IoTdevice
Alon Fliess
 
Lessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL APILessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL API
Dirk-Jan Rutten
 
The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202
Mahmoud Samir Fayed
 
Angular2 + rxjs
Angular2 + rxjsAngular2 + rxjs
Angular2 + rxjs
Christoffer Noring
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
Jorge Ortiz
 
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Performant APIs with GraphQL and PHP (Dutch PHP 2019)Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Andrew Rota
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
Christoffer Noring
 
Hidden Docs in Angular
Hidden Docs in AngularHidden Docs in Angular
Hidden Docs in Angular
Yadong Xie
 
Integrating React.js Into a PHP Application: Dutch PHP 2019
Integrating React.js Into a PHP Application: Dutch PHP 2019Integrating React.js Into a PHP Application: Dutch PHP 2019
Integrating React.js Into a PHP Application: Dutch PHP 2019
Andrew Rota
 

What's hot (12)

Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
 
What's new in c# 10
What's new in c# 10What's new in c# 10
What's new in c# 10
 
Generating cross platform .NET based azure IoTdevice
Generating cross platform .NET based azure IoTdeviceGenerating cross platform .NET based azure IoTdevice
Generating cross platform .NET based azure IoTdevice
 
Lessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL APILessons Learned Implementing a GraphQL API
Lessons Learned Implementing a GraphQL API
 
The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202
 
Angular2 + rxjs
Angular2 + rxjsAngular2 + rxjs
Angular2 + rxjs
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
 
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Performant APIs with GraphQL and PHP (Dutch PHP 2019)Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
 
Hidden Docs in Angular
Hidden Docs in AngularHidden Docs in Angular
Hidden Docs in Angular
 
Integrating React.js Into a PHP Application: Dutch PHP 2019
Integrating React.js Into a PHP Application: Dutch PHP 2019Integrating React.js Into a PHP Application: Dutch PHP 2019
Integrating React.js Into a PHP Application: Dutch PHP 2019
 

Similar to Mobile Fest 2018. Кирилл Розов. Insert Koin

KOIN for dependency Injection
KOIN for dependency InjectionKOIN for dependency Injection
KOIN for dependency Injection
Kirill Rozov
 
Build pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSLBuild pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSL
Anton Arhipov
 
API 통신, Retrofit 대신 Ktor 어떠신가요.pdf
API 통신, Retrofit 대신 Ktor 어떠신가요.pdfAPI 통신, Retrofit 대신 Ktor 어떠신가요.pdf
API 통신, Retrofit 대신 Ktor 어떠신가요.pdf
ssuserb6c2641
 
Protocol-Oriented Programming in Swift
Protocol-Oriented Programming in SwiftProtocol-Oriented Programming in Swift
Protocol-Oriented Programming in Swift
Oleksandr Stepanov
 
Icpc08b.ppt
Icpc08b.pptIcpc08b.ppt
Building a TV show with Angular, Bootstrap, and Web Services
Building a TV show with Angular, Bootstrap, and Web ServicesBuilding a TV show with Angular, Bootstrap, and Web Services
Building a TV show with Angular, Bootstrap, and Web Services
David Giard
 
Volto Extensibility Story: Plone Conference 2018
Volto Extensibility Story: Plone Conference 2018Volto Extensibility Story: Plone Conference 2018
Volto Extensibility Story: Plone Conference 2018
Rob Gietema
 
Use Geth to Deploy Contract
Use Geth to Deploy ContractUse Geth to Deploy Contract
Use Geth to Deploy Contract
KC Tam
 
Making Things Work Together
Making Things Work TogetherMaking Things Work Together
Making Things Work TogetherSubbu Allamaraju
 
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...Jerry Chou
 
How to create your own Volto site!
How to create your own Volto site!How to create your own Volto site!
How to create your own Volto site!
Rob Gietema
 
Linq intro
Linq introLinq intro
Linq intro
Bình Trọng Án
 
CAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptxCAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptx
Surajgroupsvideo
 
angular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfangular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdf
NuttavutThongjor1
 
Introduction to Python.Net
Introduction to Python.NetIntroduction to Python.Net
Introduction to Python.Net
Stefan Schukat
 
CIRCUIT 2015 - Content API's For AEM Sites
CIRCUIT 2015 - Content API's For AEM SitesCIRCUIT 2015 - Content API's For AEM Sites
CIRCUIT 2015 - Content API's For AEM Sites
ICF CIRCUIT
 
apidays LIVE Australia 2020 - From micro to macro-coordination through domain...
apidays LIVE Australia 2020 - From micro to macro-coordination through domain...apidays LIVE Australia 2020 - From micro to macro-coordination through domain...
apidays LIVE Australia 2020 - From micro to macro-coordination through domain...
apidays
 
Serverless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applicationsServerless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applications
Loiane Groner
 

Similar to Mobile Fest 2018. Кирилл Розов. Insert Koin (20)

KOIN for dependency Injection
KOIN for dependency InjectionKOIN for dependency Injection
KOIN for dependency Injection
 
Build pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSLBuild pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSL
 
API 통신, Retrofit 대신 Ktor 어떠신가요.pdf
API 통신, Retrofit 대신 Ktor 어떠신가요.pdfAPI 통신, Retrofit 대신 Ktor 어떠신가요.pdf
API 통신, Retrofit 대신 Ktor 어떠신가요.pdf
 
Protocol-Oriented Programming in Swift
Protocol-Oriented Programming in SwiftProtocol-Oriented Programming in Swift
Protocol-Oriented Programming in Swift
 
Icpc08b.ppt
Icpc08b.pptIcpc08b.ppt
Icpc08b.ppt
 
Building a TV show with Angular, Bootstrap, and Web Services
Building a TV show with Angular, Bootstrap, and Web ServicesBuilding a TV show with Angular, Bootstrap, and Web Services
Building a TV show with Angular, Bootstrap, and Web Services
 
Os Johnson
Os JohnsonOs Johnson
Os Johnson
 
Volto Extensibility Story: Plone Conference 2018
Volto Extensibility Story: Plone Conference 2018Volto Extensibility Story: Plone Conference 2018
Volto Extensibility Story: Plone Conference 2018
 
Use Geth to Deploy Contract
Use Geth to Deploy ContractUse Geth to Deploy Contract
Use Geth to Deploy Contract
 
Making Things Work Together
Making Things Work TogetherMaking Things Work Together
Making Things Work Together
 
Hems
HemsHems
Hems
 
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
 
How to create your own Volto site!
How to create your own Volto site!How to create your own Volto site!
How to create your own Volto site!
 
Linq intro
Linq introLinq intro
Linq intro
 
CAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptxCAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptx
 
angular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfangular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdf
 
Introduction to Python.Net
Introduction to Python.NetIntroduction to Python.Net
Introduction to Python.Net
 
CIRCUIT 2015 - Content API's For AEM Sites
CIRCUIT 2015 - Content API's For AEM SitesCIRCUIT 2015 - Content API's For AEM Sites
CIRCUIT 2015 - Content API's For AEM Sites
 
apidays LIVE Australia 2020 - From micro to macro-coordination through domain...
apidays LIVE Australia 2020 - From micro to macro-coordination through domain...apidays LIVE Australia 2020 - From micro to macro-coordination through domain...
apidays LIVE Australia 2020 - From micro to macro-coordination through domain...
 
Serverless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applicationsServerless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applications
 

More from MobileFest2018

Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile PoetsMobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
MobileFest2018
 
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexyMobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
MobileFest2018
 
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOSMobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
MobileFest2018
 
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
MobileFest2018
 
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
MobileFest2018
 
Mobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
Mobile Fest 2018. Yonatan Levin. WTF with Android Background RestrictionsMobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
Mobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
MobileFest2018
 
Mobile Fest 2018. Алексей Лизенко. Make your project great again
Mobile Fest 2018. Алексей Лизенко. Make your project great againMobile Fest 2018. Алексей Лизенко. Make your project great again
Mobile Fest 2018. Алексей Лизенко. Make your project great again
MobileFest2018
 
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
MobileFest2018
 
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложенийMobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
MobileFest2018
 
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
MobileFest2018
 
Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading
Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threadingMobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading
Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading
MobileFest2018
 
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
MobileFest2018
 
Mobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. БолеутоляющееMobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. Болеутоляющее
MobileFest2018
 

More from MobileFest2018 (13)

Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile PoetsMobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
 
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexyMobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
 
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOSMobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
 
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
 
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
 
Mobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
Mobile Fest 2018. Yonatan Levin. WTF with Android Background RestrictionsMobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
Mobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
 
Mobile Fest 2018. Алексей Лизенко. Make your project great again
Mobile Fest 2018. Алексей Лизенко. Make your project great againMobile Fest 2018. Алексей Лизенко. Make your project great again
Mobile Fest 2018. Алексей Лизенко. Make your project great again
 
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
 
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложенийMobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
 
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
 
Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading
Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threadingMobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading
Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading
 
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
 
Mobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. БолеутоляющееMobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. Болеутоляющее
 

Recently uploaded

Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Dr. Vinod Kumar Kanvaria
 
World environment day ppt For 5 June 2024
World environment day ppt For 5 June 2024World environment day ppt For 5 June 2024
World environment day ppt For 5 June 2024
ak6969907
 
Executive Directors Chat Leveraging AI for Diversity, Equity, and Inclusion
Executive Directors Chat  Leveraging AI for Diversity, Equity, and InclusionExecutive Directors Chat  Leveraging AI for Diversity, Equity, and Inclusion
Executive Directors Chat Leveraging AI for Diversity, Equity, and Inclusion
TechSoup
 
Delivering Micro-Credentials in Technical and Vocational Education and Training
Delivering Micro-Credentials in Technical and Vocational Education and TrainingDelivering Micro-Credentials in Technical and Vocational Education and Training
Delivering Micro-Credentials in Technical and Vocational Education and Training
AG2 Design
 
A Survey of Techniques for Maximizing LLM Performance.pptx
A Survey of Techniques for Maximizing LLM Performance.pptxA Survey of Techniques for Maximizing LLM Performance.pptx
A Survey of Techniques for Maximizing LLM Performance.pptx
thanhdowork
 
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdfMASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
goswamiyash170123
 
Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.
Ashokrao Mane college of Pharmacy Peth-Vadgaon
 
"Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe..."Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe...
SACHIN R KONDAGURI
 
Best Digital Marketing Institute In NOIDA
Best Digital Marketing Institute In NOIDABest Digital Marketing Institute In NOIDA
Best Digital Marketing Institute In NOIDA
deeptiverma2406
 
A Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in EducationA Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in Education
Peter Windle
 
Landownership in the Philippines under the Americans-2-pptx.pptx
Landownership in the Philippines under the Americans-2-pptx.pptxLandownership in the Philippines under the Americans-2-pptx.pptx
Landownership in the Philippines under the Americans-2-pptx.pptx
JezreelCabil2
 
S1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptxS1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptx
tarandeep35
 
The simplified electron and muon model, Oscillating Spacetime: The Foundation...
The simplified electron and muon model, Oscillating Spacetime: The Foundation...The simplified electron and muon model, Oscillating Spacetime: The Foundation...
The simplified electron and muon model, Oscillating Spacetime: The Foundation...
RitikBhardwaj56
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
MysoreMuleSoftMeetup
 
How to Build a Module in Odoo 17 Using the Scaffold Method
How to Build a Module in Odoo 17 Using the Scaffold MethodHow to Build a Module in Odoo 17 Using the Scaffold Method
How to Build a Module in Odoo 17 Using the Scaffold Method
Celine George
 
Thesis Statement for students diagnonsed withADHD.ppt
Thesis Statement for students diagnonsed withADHD.pptThesis Statement for students diagnonsed withADHD.ppt
Thesis Statement for students diagnonsed withADHD.ppt
EverAndrsGuerraGuerr
 
Advantages and Disadvantages of CMS from an SEO Perspective
Advantages and Disadvantages of CMS from an SEO PerspectiveAdvantages and Disadvantages of CMS from an SEO Perspective
Advantages and Disadvantages of CMS from an SEO Perspective
Krisztián Száraz
 
Normal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of LabourNormal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of Labour
Wasim Ak
 
MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...
MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...
MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...
NelTorrente
 
Digital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion DesignsDigital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion Designs
chanes7
 

Recently uploaded (20)

Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
 
World environment day ppt For 5 June 2024
World environment day ppt For 5 June 2024World environment day ppt For 5 June 2024
World environment day ppt For 5 June 2024
 
Executive Directors Chat Leveraging AI for Diversity, Equity, and Inclusion
Executive Directors Chat  Leveraging AI for Diversity, Equity, and InclusionExecutive Directors Chat  Leveraging AI for Diversity, Equity, and Inclusion
Executive Directors Chat Leveraging AI for Diversity, Equity, and Inclusion
 
Delivering Micro-Credentials in Technical and Vocational Education and Training
Delivering Micro-Credentials in Technical and Vocational Education and TrainingDelivering Micro-Credentials in Technical and Vocational Education and Training
Delivering Micro-Credentials in Technical and Vocational Education and Training
 
A Survey of Techniques for Maximizing LLM Performance.pptx
A Survey of Techniques for Maximizing LLM Performance.pptxA Survey of Techniques for Maximizing LLM Performance.pptx
A Survey of Techniques for Maximizing LLM Performance.pptx
 
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdfMASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
 
Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.
 
"Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe..."Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe...
 
Best Digital Marketing Institute In NOIDA
Best Digital Marketing Institute In NOIDABest Digital Marketing Institute In NOIDA
Best Digital Marketing Institute In NOIDA
 
A Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in EducationA Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in Education
 
Landownership in the Philippines under the Americans-2-pptx.pptx
Landownership in the Philippines under the Americans-2-pptx.pptxLandownership in the Philippines under the Americans-2-pptx.pptx
Landownership in the Philippines under the Americans-2-pptx.pptx
 
S1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptxS1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptx
 
The simplified electron and muon model, Oscillating Spacetime: The Foundation...
The simplified electron and muon model, Oscillating Spacetime: The Foundation...The simplified electron and muon model, Oscillating Spacetime: The Foundation...
The simplified electron and muon model, Oscillating Spacetime: The Foundation...
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
 
How to Build a Module in Odoo 17 Using the Scaffold Method
How to Build a Module in Odoo 17 Using the Scaffold MethodHow to Build a Module in Odoo 17 Using the Scaffold Method
How to Build a Module in Odoo 17 Using the Scaffold Method
 
Thesis Statement for students diagnonsed withADHD.ppt
Thesis Statement for students diagnonsed withADHD.pptThesis Statement for students diagnonsed withADHD.ppt
Thesis Statement for students diagnonsed withADHD.ppt
 
Advantages and Disadvantages of CMS from an SEO Perspective
Advantages and Disadvantages of CMS from an SEO PerspectiveAdvantages and Disadvantages of CMS from an SEO Perspective
Advantages and Disadvantages of CMS from an SEO Perspective
 
Normal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of LabourNormal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of Labour
 
MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...
MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...
MATATAG CURRICULUM: ASSESSING THE READINESS OF ELEM. PUBLIC SCHOOL TEACHERS I...
 
Digital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion DesignsDigital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion Designs
 

Mobile Fest 2018. Кирилл Розов. Insert Koin

  • 1. Kiev 2018 Absolute Mobile Fest Kirill Rozov Android Developer
  • 3. Kiev 2018Insert Koin Inversion of Control (IoC) is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework wikipedia.org/wiki/Inversion_of_control
  • 4. Kiev 2018Insert Koin Inversion of Control CLIENT CLIENT CLIENT DEPENDENCY 1 DEPENDENCY 2 DEPENDENCY 3 DEPENDENCY 4
  • 5. Kiev 2018Insert Koin Inversion of Control DEPENDENCY 1 DEPENDENCY 2 DEPENDENCY 3 DEPENDENCY 4 IoC CONTAINER CLIENT CLIENT CLIENT
  • 6. Kiev 2018Insert Koin Inversion of Control DEPENDENCY 1 DEPENDENCY 2 DEPENDENCY 3 DEPENDENCY 4 IoC CONTAINER CLIENT CLIENT CLIENT
  • 7. Kiev 2018Insert Koin Popular DI • Guice • Spring DI • Square Dagger • Google Dagger 2 • Java EE CDI • PicoContainer • Kodein • Koin
  • 10. Kiev 2018Insert Koin Sample val sampleModule = applicationContext { bean { ComponentA() } }
  • 11. Kiev 2018Insert Koin Sample val sampleModule = applicationContext { bean { ComponentA() } }
  • 12. Kiev 2018Insert Koin Sample val sampleModule = applicationContext { bean { ComponentA() } } class Application : KoinComponent { val component by inject<ComponentA>() }
  • 13. Kiev 2018Insert Koin Sample val sampleModule = applicationContext { bean { ComponentA() } } class Application : KoinComponent { val component by inject<ComponentA>() }
  • 14. Kiev 2018Insert Koin Sample val sampleModule = applicationContext { bean { ComponentA() } } class Application : KoinComponent { val component by inject<ComponentA>() } fun main(vararg args: String) { startKoin(listOf(sampleModule)) }
  • 15. Kiev 2018Insert Koin Init class SampleApplication : Application() { override fun onCreate() { startKoin(this, listOf(sampleModule)) } } fun main(vararg args: String) { start(listOf(sampleModule)) { … } } fun main(vararg args: String) { startKoin(listOf(sampleModule)) }
  • 16. Kiev 2018Insert Koin KoinComponent fun <T> KoinComponent.inject(name: String) : Lazy<T> fun <T> KoinComponent.inject(name: String, paras: Parameters) : Lazy<T> fun <T> KoinComponent.property(key: String) : T fun <T> KoinComponent.property(key: String, defaultValue: T) : T fun <T> KoinComponent.get(name: String) : T fun <T> KoinComponent.get(name: String, params: Parameters) : T fun KoinComponent.setProperty(key: String, value: Any) fun KoinComponent.releaseContext(name: String) fun KoinComponent.releaseProperties(vararg keys: String) interface KoinComponent
  • 17. Kiev 2018Insert Koin KoinComponent fun <T> KoinComponent.inject(name: String) : Lazy<T> fun <T> KoinComponent.inject(name: String, paras: Parameters) : Lazy<T> fun <T> KoinComponent.property(key: String) : T fun <T> KoinComponent.property(key: String, defaultValue: T) : T fun <T> KoinComponent.get(name: String) : T fun <T> KoinComponent.get(name: String, params: Parameters) : T fun KoinComponent.setProperty(key: String, value: Any) fun KoinComponent.releaseContext(name: String) fun KoinComponent.releaseProperties(vararg keys: String)
  • 18. Kiev 2018Insert Koin KoinComponent fun <T> ComponentCallbacks.inject(name: String) : Lazy<T> fun <T> ComponentCallbacks.inject(name: String, paras: Parameters) : Lazy<T> fun <T> ComponentCallbacks.property(key: String) : T fun <T> ComponentCallbacks.property(key: String, defaultValue: T) : T fun <T> ComponentCallbacks.get(name: String) : T fun <T> ComponentCallbacks.get(name: String, params: Parameters) : T fun ComponentCallbacks.setProperty(key: String, value: Any) fun ComponentCallbacks.releaseContext(name: String) fun ComponentCallbacks.releaseProperties(vararg keys: String)
  • 19. Kiev 2018Insert Koin Provide dependencies applicationContext { bean { ComponentA() } factory { ComponentB() } }
  • 20. Kiev 2018Insert Koin Provide dependencies applicationContext { bean { ComponentA() } factory { ComponentB() } }
  • 21. Kiev 2018Insert Koin Provide dependencies class ComponentA(c : ComponentB)
  • 22. Kiev 2018Insert Koin Provide dependencies applicationContext { bean { ComponentB() } bean { ComponentA(get<ComponentB>()) } } class ComponentA(c : ComponentB)
  • 23. Kiev 2018Insert Koin Named dependencies applicationContext { bean { ComponentB(…) } bean { ComponentB(…) } }
  • 24. Kiev 2018Insert Koin Named dependencies applicationContext { bean(“debug”) { ComponentB(…) } bean(“prod”) { ComponentB(…) } }
  • 25. Kiev 2018Insert Koin Named dependencies applicationContext { bean(“debug”) { ComponentB(…) } bean(“prod”) { ComponentB(…) } bean { ComponentA(get(“debug”)) } }
  • 26. Kiev 2018Insert Koin Named dependencies applicationContext { bean(“debug”) { ComponentB() } bean(“prod”) { ComponentB() } bean { ComponentA(get(“debug”)) } } class Application : KoinComponent { val componentProd by inject<ComponentB>(“prod”) val componentDebug by inject<ComponentB>(“debug”) }
  • 27. Kiev 2018Insert Koin Type binding applicationContext { bean { ComponentImpl() } bean { ComponentImpl() as Component } bean { ComponentImpl() } bind Component::class }
  • 29. Kiev 2018Insert Koin Properties class RestService(url: String)
  • 30. Kiev 2018Insert Koin Properties applicationContext { bean { RestService(getProperty(“url”)) } } class RestService(url: String)
  • 31. Kiev 2018Insert Koin Properties applicationContext { bean { RestService(getProperty(“url”)) } } class RestService(url: String) applicationContext { bean { RestService(getProperty(“url”, “http://localhost”)) } }
  • 32. Kiev 2018Insert Koin Properties applicationContext { bean { RestService(getProperty(“url”)) } } class RestService(url: String) applicationContext { bean { RestService(getProperty(“url”, “http://localhost”)) } } val key1Property: String by property(“key1”)
  • 33. Kiev 2018Insert Koin Properties startKoin(properties: Map<String, Any> = mapOf(“key” to 1))
  • 34. Kiev 2018Insert Koin Properties Sources • koin.properties in JAR resources • koin.properties in assets • Environment properties
  • 35. Kiev 2018Insert Koin Environment variables startKoin(useEnvironmentProperties = true) // Get user name from properties val key1Property: String by property(“USER”)
  • 36. Kiev 2018Insert Koin Problem class NewsDetailPresenter(newsId : String)
  • 37. Kiev 2018Insert Koin Parameters val presenter: NewsDetailPresenter by inject { mapOf(NEWS_ID to "sample") }
  • 38. Kiev 2018Insert Koin Parameters applicationContext { factory { params: ParametersProvider -> NewsDetailsPresenter(params[NEWS_ID]) } } val presenter: NewsDetailPresenter by inject { mapOf(NEWS_ID to "sample") }
  • 39. Kiev 2018Insert Koin Parameters applicationContext { factory { params: ParametersProvider -> NewsDetailsPresenter(params[NEWS_ID]) } } val presenter: NewsDetailPresenter by inject { mapOf(NEWS_ID to "sample") } interface ParametersProvider { operator fun <T> get(key: String): T fun <T> getOrNull(key: String): T? }
  • 41. Kiev 2018Insert Koin Contexts applicationContext { context("main") { bean { ComponentA() } bean { ComponentB() } } }
  • 42. Kiev 2018Insert Koin Contexts applicationContext { context("main") { bean { ComponentA() } bean { ComponentB() } } } class MainActivity : Activity() { override fun onStop() { releaseContext("main") } }
  • 43. Kiev 2018Insert Koin Context isolation applicationContext { context("A") { bean { ComponentA() } context("B") { bean { ComponentB() } } } context("C") { bean { ComponentС() } } }
  • 44. Kiev 2018Insert Koin Context isolation applicationContext { context("A") { bean { ComponentA() } context("B") { bean { ComponentB() } } } context("C") { bean { ComponentС() } } }
  • 45. Kiev 2018Insert Koin Context isolation applicationContext { context("A") { bean { ComponentA() } context("B") { bean { ComponentB() } } } context("C") { bean { ComponentС() } } }
  • 46. Kiev 2018Insert Koin Context isolation applicationContext { context("A") { bean { ComponentA() } context("B") { bean { ComponentB() } } } context("C") { bean { ComponentС() } } }
  • 48. Kiev 2018Insert Koin class Presenter(repository: Repository) class Repository(dateSource: DateSource) interface DateSource class DebugDataSource() : DateSource
  • 49. Kiev 2018Insert Koin applicationContext { factory { Presenter(get()) } bean { Repository(get()) } bean { DebugDataSource() } bind DateSource::class } class Presenter(repository: Repository) class Repository(dateSource: DateSource) interface DateSource class DebugDataSource() : DateSource
  • 50. Kiev 2018Insert Koin applicationContext { factory { Presenter(get()) } bean { Repository(get()) } bean { DebugDataSource() } bind DateSource::class } get<Presenter>() get<Presenter>() class Presenter(repository: Repository) class Repository(dateSource: DateSource) interface DateSource class DebugDataSource() : DateSource
  • 51. Kiev 2018Insert Koin applicationContext { factory { Presenter(get()) } bean { Repository(get()) } bean { DebugDataSource() } bind DateSource::class } get<Presenter>() get<Presenter>() (KOIN) :: Resolve [Presenter] ~ Factory[class=Presenter] (KOIN) :: Resolve [Repository] ~ Bean[class=Repository] (KOIN) :: Resolve [Datasource] ~ Bean[class=DebugDatasource, binds~(Datasource)] (KOIN) :: (*) Created (KOIN) :: (*) Created (KOIN) :: (*) Created (KOIN) :: Resolve [Repository] ~ Factory[class=Repository] (KOIN) :: Resolve [DebugDatasource] ~ Bean[class=DebugDatasource, binds~(Datasource)] (KOIN) :: (*) Created class Presenter(repository: Repository) class Repository(dateSource: DateSource) interface DateSource class DebugDataSource() : DateSource
  • 52. Kiev 2018Insert Koin Missing dependency applicationContext { bean { ComponentA(get()) } bean { ComponentB(get()) } } class ComponentA(component: ComponentB) class ComponentB(component: ComponentA) get<ComponentC>()
  • 53. Kiev 2018Insert Koin Missing dependency applicationContext { bean { ComponentA(get()) } bean { ComponentB(get()) } } class ComponentA(component: ComponentB) class ComponentB(component: ComponentA) org.koin.error.DependencyResolutionException: No definition found for ComponentC - Check your definitions and contexts visibility get<ComponentC>()
  • 54. Kiev 2018Insert Koin Cyclic dependencies class ComponentA(component: ComponentB) class ComponentB(component: ComponentA)
  • 55. Kiev 2018Insert Koin Cyclic dependencies applicationContext { bean { ComponentA(get()) } bean { ComponentB(get()) } } class ComponentA(component: ComponentB) class ComponentB(component: ComponentA)
  • 56. Kiev 2018Insert Koin Cyclic dependencies get<ComponentA>() applicationContext { bean { ComponentA(get()) } bean { ComponentB(get()) } } class ComponentA(component: ComponentB) class ComponentB(component: ComponentA)
  • 57. Kiev 2018Insert Koin Cyclic dependencies org.koin.error.BeanInstanceCreationException: Can't create bean Bean[class=ComponentA] due to error : BeanInstanceCreationException: Can't create bean Bean[class=ComponentB] due to error : BeanInstanceCreationException: Can't create bean Bean[class=ComponentA] due to error : DependencyResolutionException: Cyclic dependency detected while resolving class ComponentA applicationContext { bean { ComponentA(get()) } bean { ComponentB(get()) } } class ComponentA(component: ComponentB) class ComponentB(component: ComponentA) get<ComponentA>()
  • 59. Kiev 2018Insert Koin Tests class SampleTest : KoinTest { val presenter : MyPresenter by inject() val repository : Repository by inject() @Before fun before(){ startKoin(listOf(myModule)) } @Test fun testSayHello() { val hello = repository.giveHello() assertEquals(hello, presenter.sayHello()) } @After fun after(){ closeKoin() } }
  • 60. Kiev 2018Insert Koin Tests class SampleTest : KoinTest { val presenter : MyPresenter by inject() val repository : Repository by inject() @Before fun before(){ startKoin(listOf(myModule)) } @Test fun testSayHello() { val hello = repository.giveHello() assertEquals(hello, presenter.sayHello()) } @After fun after(){ closeKoin() } }
  • 61. Kiev 2018Insert Koin Tests class SampleTest : KoinTest { val presenter : MyPresenter by inject() val repository : Repository by inject() @Before fun before(){ startKoin(listOf(myModule)) } @Test fun testSayHello() { val hello = repository.giveHello() assertEquals(hello, presenter.sayHello()) } @After fun after(){ closeKoin() } }
  • 62. Kiev 2018Insert Koin Tests class SampleTest : KoinTest { val presenter : MyPresenter by inject() val repository : Repository by inject() @Before fun before(){ startKoin(listOf(myModule)) } @Test fun testSayHello() { val hello = repository.giveHello() assertEquals(hello, presenter.sayHello()) } @After fun after(){ closeKoin() } }
  • 64. Kiev 2018Insert Koin Graph validation class ComponentA(component: ComponentB) class ComponentB(component: ComponentC) class ComponentC()
  • 65. Kiev 2018Insert Koin Graph validation class ComponentA(component: ComponentB) class ComponentB(component: ComponentC) class ComponentC() val sampleModule = applicationContext { bean { ComponentA(get()) } factory { ComponentB(get()) } }
  • 66. Kiev 2018Insert Koin Graph validation class ComponentA(component: ComponentB) class ComponentB(component: ComponentC) class ComponentC() val sampleModule = applicationContext { bean { ComponentA(get()) } factory { ComponentB(get()) } } class DryRunTest : KoinTest { @Test fun dryRunTest() { startKoin(listOf(sampleModule)) dryRun() } }
  • 67. Kiev 2018Insert Koin Android Arch Components
  • 68. Kiev 2018Insert Koin Default Way class ListFragment : Fragment() { val listViewModel = ViewModelProviders.of(this).get(ListViewModel::class.java) }
  • 69. Kiev 2018Insert Koin Simpler with Kotlin class ListFragment : Fragment() { val listViewModel = getViewModel<ListViewModel>() } inline fun <reified VM : ViewModel> Fragment.getViewModel():VM { return viewModelProvider.get(VM::class.java) }
  • 70. Kiev 2018Insert Koin ViewModel with arguments class DetailViewModel(id: String) : ViewModel()
  • 71. Kiev 2018Insert Koin ViewModel with arguments class DetailViewModel(id: String) : ViewModel() class DetailFactory(val id: String) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass == DetailViewModel::class.java) { return DetailViewModel(id) as T } error("Can't create ViewModel for class='$modelClass'") } }
  • 72. Kiev 2018Insert Koin ViewModel with arguments class DetailViewModel(id: String) : ViewModel() class DetailFactory(val id: String) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass == DetailViewModel::class.java) { return DetailViewModel(id) as T } error("Can't create ViewModel for class='$modelClass'") } } class ListFragment : Fragment() { val listViewModel = provideViewModel<DetailViewModel>(DetailFactory(id)) }
  • 73. Kiev 2018Insert Koin Koin Way applicationContext { viewModel { params -> DetailViewModel(params["id"]) } }
  • 74. Kiev 2018Insert Koin Koin Way applicationContext { viewModel { params -> DetailViewModel(params["id"]) } } class ListFragment : Fragment() { val listViewModel by viewModel<ListViewModel> { mapOf("id" to "sample") } }
  • 76. Kiev 2018Insert Koin What missed from Dagger 2? • Compile time validation • Features • Multibindings • Async Injection • Reusable scope
  • 77. Kiev 2018Insert Koin Why use Koin? • Dagger 2 is too complex for start with DI • No need Dagger 2 advanced features • Single place of dependencies declaration • DSL is amazing for dependencies declaration • Support Kotlin Multiplatform projects • Faster build time • Pure Kotlin code
  • 78. Kiev 2018Insert Koin Thanks insert-Koin.io kiryl.rozau@apalon.com krlrozov