Slide 1

Slide 1 text

KOIN (Dependency Injection)

Slide 2

Slide 2 text

About Me Rozina Darediya Android Developer at Theta Technolabs Kotlin/ Java Enthusiast : rozina_02

Slide 3

Slide 3 text

We will cover today: Introduction to Dependency Injection & KOIN

Slide 4

Slide 4 text

DEPENDENCY INJECTION

Slide 5

Slide 5 text

Dependency Injection ??? Ohh no !!!

Slide 6

Slide 6 text

Dependency Injection ???

Slide 7

Slide 7 text

Dependency Injection: What is DI : ❖  Design pattern/concept of OOPs ❖  Don’t create an object of another class inside a class ❖  Instead, we supply the needed object from outside.

Slide 8

Slide 8 text

Dependency Injection: What is DI : ❖  Classes often require references to other classes ➢  Car() ===> Engine() ➢  These required classes are called dependencies ➢  Car class is dependent on having an instance of the Engine class to run ●  Car() creates obj of Engine() ●  Tightly coupled/highly dependent ●  Engine() need to be change its definition, than Car also need to change its definition.

Slide 9

Slide 9 text

What is DI : Receives object Engine() as a parameter in its constructor

Slide 10

Slide 10 text

Definition : In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used (a service).

Slide 11

Slide 11 text

DI work:

Slide 12

Slide 12 text

Why DI : ❖  Helps us enable loose coupling ❖  Reduces the boilerplate code ❖  Reusable and clean code ❖  Easy to replace dependencies with fake implementations ❖  Easier to test

Slide 13

Slide 13 text

Popular libraries for DI : (some names we have heard of) ❖  RoboGuice (no longer supported,Inject your View, Resource, System Service, or any other object) ❖  ButterKnife (Field and method binding for Android views) ❖  Dagger (compile-time framework for dependency injection) ❖  Koin (A pragmatic lightweight dependency injection framework)

Slide 14

Slide 14 text

Dagger and its pitfalls ❖  Initial setup is difficult ❖  Bit complex to learn ❖  Unclear compile time errors ❖  Increased time in compilation process ❖  Uses reflection to some extent

Slide 15

Slide 15 text

Dagger and its pitfalls Source

Slide 16

Slide 16 text

Dagger and its pitfalls Source

Slide 17

Slide 17 text

Here comes KOIN to rescue..

Slide 18

Slide 18 text

Introduction : KOIN ❖  Pragmatic lightweight DSL dependency injection framework ❖  Purely written in Kotlin ❖  Easy, simple, well documented ❖  No proxy ❖  No code generation ❖  No reflection

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Install the dependency First get the library into your project. You will need to add the following to your module-level build.gradle.

Slide 21

Slide 21 text

KOIN in three stages According to the official documentation, you can start using Koin in three simple stages ❖  Declare a module ❖  Start Koin ❖  Perform an injection

Slide 22

Slide 22 text

Declare a Module

Slide 23

Slide 23 text

Start Koin

Slide 24

Slide 24 text

Perform an injection

Slide 25

Slide 25 text

Perform an injection By the way, there are two ways of providing the type: via a type parameter or via an explicit type definition: 1.  val toastMessage by inject() 2.  val anotherToastMessage : ToastMessage by inject()

Slide 26

Slide 26 text

Perform an injection

Slide 27

Slide 27 text

Task in ToastMessage

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

Dipper dive with KOIN ❖  With Koin, setting up dependency injection is kind of a manual process ❖  We essentially plug our services into the module graphs ❖  These dependencies will later get resolved at runtime

Slide 30

Slide 30 text

Some key functions Some key functions ❖  module { } : ➢  Create a Koin Module or a submodule (inside a module) ➢  It serves as a container ➢  It is a collection of services that should be provided at runtime. ➢  We put all the services that a module should provide in the module block

Slide 31

Slide 31 text

Some key functions ❖  factory{ } : ➢  Creates instance of given class. ➢  new instance every time it’s called. ➢  Can be dropped ➢  Koin will resolve all the dependencies of MyClass

Slide 32

Slide 32 text

➢  Manually build the dependency ➢  Used this when want to build a dependency based on configurations or other criteria.

Slide 33

Slide 33 text

Some key functions ❖  single{ } : ➢  Create object persist entire lifetime ➢  Can’t be dropped ➢  This can be done in some ways similar to the factory defined above.

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

Some key functions ❖  get{ } : ➢  Is a generic function ➢  Use to resolve any particular dependency that you need ➢  To the requested needed component instance. class Service() class Controller( val view : View)

Slide 36

Slide 36 text

private lateinit var someService: SomeInterface

Slide 37

Slide 37 text

Read or Write Properties ❖  setProperty/getProperty : ➢  Koin can contain configuration properties or values ➢  that can be read and set at runtime ➢  key-value pair container // set the property at run time setProperty("api_url", "http://dummy.dev.com") // get the property val stagingUrl: String = getProperty("api_url")

Slide 38

Slide 38 text

KOIN component ➢  Koin creates its dependency container when we start a Koin ➢  To retrieve dependencies or interact with Koin, you would need to implement KoinComponent ➢  KoinComponent serves as the container context ➢  Allows you to interact with the Koin framework ➢  Access to functions like get, inject, getKoin, viewModel, etc.

Slide 39

Slide 39 text

❖  In activity no need of KoinComponent // dependency evaluates eagerly val toastMessage : ToastMessage = get() //dependency evaluates lazily val toastMessage : ToastMessage by inject() ●  In first, the Object creation gets to the field initialization (will be retrieved from the dependency container) ●  In second, it will not be resolved until the class tries to use it

Slide 40

Slide 40 text

❖  In non-lifecycle component, KoinComponent is needed ➢  BroadcastReceiver has to implement KoinComponent to interact with Koin.

Slide 41

Slide 41 text

❖  In ViewModel KoinComponent(ViewModel) is needed ➢  viewModel { } definition enables to define a viewModel dependency ➢  Define dependency val activityModule = module { viewModel { ActivityViewModel() } } ➢  Declare viewModel in activity or fragment val activityViewModel: ActivityViewModel by viewModel() ➢  Declare viewModel that is shared between activity and its child fragments val mainActivityViewModel: MainActivityViewModel by sharedViewModel()

Slide 42

Slide 42 text

Scope in KOIN

Slide 43

Slide 43 text

➢  Scope will decide how long is the lifecycle of injected object. ➢  It allows you to define local scoped-dependencies ➢  Like - Presenter, View Adapter, or other service components ➢  They are meant to be short-lived within a defined scope, ○  like an Activity’s scope ➢  Specify the scope_id which is just a unique string to represent the scope definition ➢  scope_id will be used as a reference, ○  in creating, requesting or closing a scope.

Slide 44

Slide 44 text

➢  Define scope: val myPresenterModule = module { scope("myPresenter") { MyPresenter() } } ➢  Bind the Scope to the Activity using bind into the onCreate method. override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val scope = getKoin().getOrCreateScope("myPresenter") bindScope(scope) } ➢  scope.close()

Slide 45

Slide 45 text

Testing with KOIN

Slide 46

Slide 46 text

➢  Add library of test : dependencies { // Koin testing tools testImplementation 'org.koin:koin-test:$koin_version' } ➢  Just tag your test class with KoinTest ➢  and you will be able to use KoinComponent & testing features ○  by inject() - lazy inject an instance ○  get() - retrieve an instance

Slide 47

Slide 47 text

val testModule = module { single { TestData(4, 2 + 5) } } data class TestData(val expected: Long, val actual: Long) class ExampleUnitTest : KoinTest { val testData: TestData by inject() @Before fun before() { startKoin { modules(testModule) } } @After fun after() { stopKoin() } @Test fun addition_isCorrect() { assertEquals(testData.expected, testData.actual) } }

Slide 48

Slide 48 text

Thank You