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.
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)
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()
injection is kind of a manual process ❖ We essentially plug our services into the module graphs ❖ These dependencies will later get resolved at runtime
: ➢ 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
generic function ➢ Use to resolve any particular dependency that you need ➢ To the requested needed component instance. class Service() class Controller( val view : View)
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")
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.
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
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()
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.
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()
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
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) } }