Share
Embed
Transcript
48 slides
-
About Me Rozina Darediya Android Developer at Theta Technolabs Kotlin/
Java Enthusiast : rozina_02 -
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. -
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. -
What is DI : Receives object Engine() as a parameter
in its constructor -
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). -
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 -
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) -
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 -
Introduction : KOIN ❖ Pragmatic lightweight DSL dependency injection framework
❖ Purely written in Kotlin ❖ Easy, simple, well documented ❖ No proxy ❖ No code generation ❖ No reflection -
Install the dependency First get the library into your project.
You will need to add the following to your module-level build.gradle. -
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 -
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<ToastMessage>() 2. val anotherToastMessage : ToastMessage by inject() -
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 -
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 -
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 -
➢ Manually build the dependency ➢ Used this when want
to build a dependency based on configurations or other criteria. -
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. -
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) -
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") -
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. -
❖ 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 -
❖ In non-lifecycle component, KoinComponent is needed ➢ BroadcastReceiver has
to implement KoinComponent to interact with Koin. -
❖ 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() -
➢ 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. -
➢ 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() -
➢ 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 -
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<TestData>() @Before fun before() { startKoin { modules(testModule) } } @After fun after() { stopKoin() } @Test fun addition_isCorrect() { assertEquals(testData.expected, testData.actual) } }