美文网首页
Android IOC注入技术—Dagger2(一)

Android IOC注入技术—Dagger2(一)

作者: 大虾啊啊啊 | 来源:发表于2022-02-18 14:29 被阅读0次

1、为什么要使用Dagger2

和Spring的思想一样, 传统创建对象需要主动new 的方式,IOC技术则是实现被动注入的方式。称之为依赖注入,也可以称之为控制反转。目的就是为了代码的解耦。

2、Dagger2的简单使用

(1)添加Dagger2注解处理器和API支持

    implementation 'com.google.dagger:dagger:2.4'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.4'

根据Gradle的依赖,由此可猜到Dagger2使用到了APT注解处理器的技术,必然在Dagger2的API支持中需要使用到注解,并且Dagger2会根据注解生成相应的代码。
(2)测试注入一个Dog对象

  • 创建一个Dog类
package com.example.dagger2demo.bean;

/**
 * author : weishixiong
 * e-mail : weishixiong@pudutech.com
 * date   : 2022/2/18 11:22
 * desc   :Dog实体类
 */
public class Dog {
}

  • 创建Module,使用@Module注解将对象包裹,并开放提供Dog对象的方法
package com.example.dagger2demo.module;

import com.example.dagger2demo.bean.Dog;

import dagger.Module;
import dagger.Provides;

/**
 * author : weishixiong
 * e-mail : weishixiong@pudutech.com
 * date   : 2022/2/18 11:33
 * desc   :Dog类包裹、提供对象
 */
@Module
public class DogModule {
    @Provides
    public Dog provideDogObject() {
        return new Dog();
    }

}

  • 创建Component接口,将对象注入到指定的目标中,例子为注入到MainActivity中
package com.example.dagger2demo.component;

import com.example.dagger2demo.MainActivity;
import com.example.dagger2demo.module.DogModule;
import com.example.dagger2demo.module.PigModule;

import dagger.Component;

/**
 * author : weishixiong
 * e-mail : weishixiong@pudutech.com
 * date   : 2022/2/18 11:35
 * desc   :对象注入
 */
@Component(modules = {DogModule.class, PigModule.class})

public interface MyComponent {
    /**
     * 此处不能用多态
     *
     * @param activity
     */
    void inject(MainActivity activity);

}

  • 在MainActivity中注入对象
package com.example.dagger2demo;

import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.example.dagger2demo.bean.Dog;
import com.example.dagger2demo.bean.Pig;
import com.example.dagger2demo.component.DaggerMyComponent;

import javax.inject.Inject;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private final String TAG = getClass().getSimpleName();
    @Inject
    Dog dog;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMyComponent.create().inject(this);
    }

    public void click(View view) {
        Log.e(TAG, "click: " + dog.hashCode());
    
    }
}
2022-02-18 11:48:38.099 26775-26775/com.example.dagger2demo E/MainActivity: click: 9641581

dog对象打印出了hashcode,说明我们的对象已经注入成功。
通过一张图了解大概的注入流程:


image.png

3、源码分析(APT生成代码的部分省略)

(1)编译期使用APT生成对应的代码


image.png

(2)在MainAcrtivity初始化的时候调用 DaggerMyComponent.create().inject(this);
调用DaggerMyComponent.create()的时候创建DaggerMyComponent对象,我们在创建的对象的时候看源码发生了什么?

private Provider<Dog> provideDogObjectProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
..........
private void initialize(final Builder builder) {
  this.provideDogObjectProvider = DogModule_ProvideDogObjectFactory.create(builder.dogModule);
  this.mainActivityMembersInjector =
      MainActivity_MembersInjector.create(provideDogObjectProvider, providerPigObjectProvider);
}

@Override
public void inject(MainActivity activity) {
  mainActivityMembersInjector.injectMembers(activity);
}

public static final class Builder {
  private DogModule dogModule;
  private Builder() {}

  public MyComponent build() {
    if (dogModule == null) {
      this.dogModule = new DogModule();
    }
 
    return new DaggerMyComponent(this);
  }
....
}
  • 创建DaggerMyComponent对象的时候创建了DogModule对象,调用DogModule_ProvideDogObjectFactory.create,将DogModule包装到DogModule_ProvideDogObjectFactory provideDogObjectProvider 对象中。
  • 调用MainActivity_MembersInjector.create方法将provideDogObjectProvider 对象包装到MainActivity_MembersInjector对象中。
    再来看看inject方法,最终调用到了MainActivity_MembersInjector中的injectMembers方法,
  @Override
  public void injectMembers(MainActivity instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.dog = dogProvider.get();
  }

到这里就就很明显了将MainActivity中的dog对象赋值为 dogProvider.get();,而dogProvider中的get方法最后会调用我们的DogModule中的provideDogObject方法

 @Override
  public Dog get() {
    return Preconditions.checkNotNull(
        module.provideDogObject(), "Cannot return null from a non-@Nullable @Provides method");
  }

@Module
public class DogModule {
    @Provides
    public Dog provideDogObject() {
        return new Dog();
    }

}

到这里MainActvity中的dog对象就有值了,而这个值正式我们再DogModule 中通过provideDogObject方法提供的。
(3)源码小结

  • Module负责包装、提供对象
  • Component拿到Module提供的对象注入到指定的目标中(比如例子中的MainActivity)

相关文章

网友评论

      本文标题:Android IOC注入技术—Dagger2(一)

      本文链接:https://www.haomeiwen.com/subject/lhhylrtx.html