current position:Home>Android: a dependency injection framework

Android: a dependency injection framework

2022-01-26 23:50:19 KEN

This document is not authorized , Don't reprint


   Work in Android It has been developed for more than two years , Access to different frames , From the very beginning ButterKnife To the back Kotlin have to Kotlin-android-extensions, Here we are DataBinding and ViewBinding, One of the most impressive is not this kind of , It's not like that. RxJava2 This kind of , Instead, it relies on injection components such as Dagger2, Come back later Koin, And the latest Hilt. So let's try to see if we can write a similar framework by hand .

Preliminary analysis

I have roughly analyzed several points that we need to solve :
One 、 Without reflection based on , How to save our pre initialized content , Or the object we want to initialize .
Two 、 Scope problem , I initialized it Module The question of which scope to initialize , There is also a kind of global Module.
3、 ... and 、 When our Module Contains the life cycle of existence , Such as holding LifeOwnwer Of Activity, perhaps Fragment And so on .

Start the first line of code


The project address is here Kinject Based on the framework of Kotlin developable , Apply to reified,DSL And other grammar and methods .

If you read my article Android Development : Share how to make good use of Kotlin Characteristics ( One )---- Improve development efficiency I should be impressed. At the beginning, I talked about how to use Lazy Perform global initialization , At that time, it was the prototype of this project . If we want to inject into ViewModel What about the objects in , Need to be in Activity Use this Module, From the third point we analyzed earlier , You need to monitor the lifecycle .

Analysis preparation

Then our first step should be to build a pool to hold these Module, Well known , This pool we often use HashMap,ArraryMap And so on. KEY-VALUE pool , I'm going to use ConcurrentHashMap, For concurrency compatibility .

Let's define this first KEY, First of all, this KEY, What is needed , It's very simple. The only content , Make sure you get to the only content , Find the only answer . So there is the following :

open class Qualifier<D> {
    private var key : D? = null
    fun getKey() = key
    fun setKeyName(key:D){
        this.key = key
    override fun hashCode(): Int {
        return 31 * getKey().hashCode()
    override fun equals(other: Any?): Boolean {
        return if(other is Qualifier<*>){
            other.key == this.key
    override fun toString(): String {
        return "Qualifier[Key:${key}]"

 Copy code 

Then we mainly use string as discrimination , Then it becomes :

class StringQualifier : Qualifier<String>()

 Copy code 

KEY It's done , Then we have to decide VALUE The content of , Obviously VALUE It's ours Module,

Actually Moduel It's also very simple. , Is to save the object .

private val entrySingle by lazy { ConcurrentHashMap<String, Any>() }

private val entryFactory by lazy { ConcurrentHashMap<String, () -> Any?>() }

 Copy code 

Use two ConcurrentHashMap, The first one is for certificates of deposit or , Initialize the content once , The second storage method , Then each call will re execute the method , All new objects are as follows :


The second step , Treatment of the life cycle

In fact, at this stage, we have basically completed most of the contents of the simple framework , The next step is just to manage the areas containing the life cycle , We just need to inherit LifecycleObserver, Just remove what we store in the appropriate life cycle .

Practical application

This practical application is in another project of mine MaterialWanAndroid client Apply on , The core content is

initScope {
    module(viewModel, lifeModule {
 Copy code 

stay Activity In the ViewModel object , Inject LifeOwner, Then our warehouse XXXReposiory Just call getLifeOwner Method , as follows :

if(owner == null){
    owner = getLifeOwner(viewModel)
 Copy code 

Among them the viewModel, Is that we are Activity Initialized in viewModel.


In fact, such a simple handwriting injection framework is still relatively simple , But it does satisfy most of the development Such as singleton Retorfit Of Api

initScope {
    single { Retorfit.create( }
 Copy code 

Then in the warehouse, we just need , In this way, you can use , Databases work similarly

private val api : Main by single()

 Copy code 

copyright notice
author[KEN],Please bring the original link to reprint, thank you.

Random recommended