看完不懂Dagger2我跪搓板

0. 序言

  • 有些人说现在的架构都是Mvp+Dagger2,其实好多公司还是没有用Dagger2,因为项目的更新换代不是一天就能完成的,公司项目需要的终极目标其实是稳定,就算你不用Dagger2,依然可以实现预期的效果。
  • 使用了Dagger2的项目,优势在于代码层面解耦更好,劣势在于增加了额外类,同时维护代码的难度增加了。
  • 博文主要分为三大部分:注解、懒加载和原理分析。注解包括:
① @Inject 和 @Component
② @Module 和 @Provides
③ @Named 和 @Qualifier
④ @Singleton和@Scope
⑤ @Component的dependencies

1. 所涉及依赖:

    annotationProcessor 'com.google.dagger:dagger-compiler:2.7'
    implementation 'com.google.dagger:dagger:2.7'
    implementation 'com.google.code.gson:gson:2.8.5'

2. @Inject 和 @Component

  • 定义两个类,分别是MainActivity和Person,并在MainActivity中执行Person的eat方法
public class Person{
    public void eat(){
        Log.i("fukq","我要吃面包");
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Person person = new Person();
        person.eat();
    }
}
11-27 14:47:51.695 32317-32317/com.smartisan.dagger2 I/fukq: 我要吃面包
  • 用Dagger2改造以上示例:

2.1. 改写Person类:

public class Person{
    @Inject
    public Person() {
    }

    public void eat(){
        Log.i("fukq","我要吃面包");
    }
}

说明:这里标记Person构造方法,则表明Dagger2可以使用Person构造方法构建对象。

2.2. 创建接口MainActivityComponent指定依赖注入的目标类:

@Component
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

说明:
① 接口命令建议:目标类名+Component。
② @Component 就是告诉Dagger2依赖注入的目标是MainActivity。
③ 创建完接口后记得编译下:锤子按钮(AndroidStudio)。这样在编译后Dagger2就会为我们生成名为Dagger+目标类名+Component的辅助类,辅助类的默认生成路径如下:


image.png

2.3. 在目标类MainActivity中使用辅助类DaggerMainActivityComponent完成注入:

public class MainActivity extends AppCompatActivity {
    @Inject
    Person mPerson; // 1
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainActivityComponent.create().inject(this); // 2
        mPerson.eat();
    }
}

说明:
① Inject用来标记需要注入的实例,这个实例是以成员变量的形式出现。
② 辅助类DaggerMainActivityComponent调用inject完成注入。
③ 总结可知:Inject有三种注入方式,分别是成员变量注入和构造方法注入以及方法注入(后面会讲)。

11-27 14:57:24.679 32691-32691/com.smartisan.dagger2 I/fukq: 我要吃面包

3. @Module 和 @Provides

3.1 Dagger2引入第三方类库

如果项目使用第三方的类库,比如Gson,我们就不能把@Inject添加到Gson的构造方法中,这个时候采用@Module和@Provides来处理。

3.1.1. 创建GsonModule类:

@Module
public class GsonModule {

    @Provides
    public Gson provideGson(){
        return new Gson();
    }
}

说明:
① @Module用来告诉Component,可以从这个类获取依赖对象。
② 告诉了对象所在的类,还需要告诉Component获取依赖对象实例的方法,所以用@Provides注释方法。

3.1.2. 编写Component类MainActivityComponent:

@Component(modules = GsonModule.class)
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

说明:
① 之前已经创建了MainActivityComponent类,添加modules = GsonModule.class即可
② modules = GsonModule.class用来指定module,之所以用modules,是因为可以指定多个Module.

3.1.3. 在MainActivity中使用Gson:

public class MainActivity extends AppCompatActivity {
    @Inject
    Gson mGson;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainActivityComponent.create().inject(this);

        String jsonData = "{'name':'fukq','age':18}";
        Man man = mGson.fromJson(jsonData,Man.class);
        Log.i("fukq","name-------"+man.getName());
    }
}
public class Man{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
11-27 16:36:54.512 3275-3275/com.smartisan.dagger2 I/fukq: name-------fukq
3.2 Dagger2引入抽象对象

除了第三方仓库的引入不能使用@Inject,如果注入的对象是抽象的,那么@Inject也无法使用,因为抽象的类并不能实例化。比如:

public abstract class Engine {
    public abstract String work();
}
public class GasolineEngline extends Engine {
    @Inject
    public GasolineEngline() {
    }

    @Override
    public String work() {
        return "汽油发动机发动";
    }
}
public class Car {
    private Engine mEngine;

    @Inject
    public Car(Engine engine) {
        mEngine = engine;
    }
    public String run(){
        return mEngine.work();
    }
}

说明:这里用的Inject的构造方法注入。可能你会问哪种注入方式更好呢,这里建议构造方法注入,以后会专门拿出一篇文章来讲解这个事情。

public class MainActivity extends AppCompatActivity {
    @Inject
    Person mPerson;
    @Inject
    Gson mGson;
    @Inject
    Car mCar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainActivityComponent.create().inject(this);
        mPerson.eat();

        String jsonData = "{'name':'fukq','age':18}";
        Man man = mGson.fromJson(jsonData,Man.class);
        Log.i("fukq","name-------"+man.getName());

        String str =mCar.run();
        Log.d("fukq","car---" + str);
    }
}
error: com.smartisan.dagger2.Engine cannot be provided without an @Provides-annotated method.
com.smartisan.dagger2.Engine is injected at
com.smartisan.dagger2.Car.<init>(engine)
com.smartisan.dagger2.Car is injected at
com.smartisan.dagger2.MainActivity.mCar
com.smartisan.dagger2.MainActivity is injected at
com.smartisan.dagger2.MainActivityComponent.inject(activity)

说明:
① 这里报错了,为何呢?因为Engine是抽象的。@Inject无法提供实例。
② 这里采用@Module和@Provides来处理。
3.2.1. 修改GasolineEngline类,去掉@Inject:

public class GasolineEngline extends Engine {

    @Override
    public String work() {
        return "汽油发动机发动";
    }
}

3.2.2. 创建EngineModule:

@Module
public class EngineModule {

    @Provides
    public Engine provideEngline(){
        return new GasolineEngline();
    }
}

3.2.3. 在Component中指定EngineModule:

@Component(modules = {GsonModule.class,EngineModule.class})
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

3.2.4. 在MainActivity 注入Car:

public class MainActivity extends AppCompatActivity {
    @Inject
    Person mPerson;
    @Inject
    Gson mGson;
    @Inject
    Car mCar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainActivityComponent.create().inject(this);
        mPerson.eat();

        String jsonData = "{'name':'fukq','age':18}";
        Man man = mGson.fromJson(jsonData,Man.class);
        Log.i("fukq","name-------"+man.getName());

        String str =mCar.run();
        Log.d("fukq","car---" + str);
    }
}
11-28 11:23:20.858 19873-19873/? D/fukq: car---汽油发动机发动

4. @Named 和 @Qualifier

4.1 @Named

@Qualifier是限定符,@Named是@Qualifier的一种实现。当有两个类都继承同一个父类或者均实现同一个接口。当他们被提供给高层时,Component就不知道到底要提供哪一个依赖对象了。比如上面的汽车(父类),它有一个子类GasolineEngline,我们再提供一个子类DieselEngine给汽车(父类),如下:

public class DieselEngline extends Engine {

    @Override
    public String work() {
        return "柴油发动机发动";
    }
}
@Module
public class EngineModule {

    @Provides
    public Engine provideGasoline(){
        return new GasolineEngline();
    }

    @Provides
    public Engine provideDiesel(){
        return new DieselEngline();
    }
}

这个时候我们提供了两个Provides,Component不知道选哪个,这个时候@Named就派上了用场,它的作用就是起别名(外号)。

4.1.1 对EngineModule进行改造:

@Module
public class EngineModule {

    @Provides
    @Named ("Gasoline")
    public Engine provideGasoline(){
        return new GasolineEngline();
    }

    @Provides
    @Named ("Diesel")
    public Engine provideDiesel(){
        return new DieselEngline();
    }
}

4.1.2 在Car类(父类)指定要采用哪个Provides:

public class Car {
    private Engine mEngine;

    @Inject
    public Car(@Named("Diesel") Engine engine) {
        mEngine = engine;
    }
    public String run(){
        return mEngine.work();
    }
}
11-28 14:10:18.815 22163-22163/com.smartisan.dagger2 D/fukq: car---柴油发动机发动
4.2 @Qualifier

@Named 传递的值只能是字符串,而@Qualifier 则更灵活一些,@Qualifier不是直接标记在属性上的,而是用来自定义注解的,如下:

4.2.1 定义两个不同的注解(自定义注解以后会写一篇博文来讲解)

@Qualifier
@Retention(RUNTIME)
public @interface Gasloline {
}
@Qualifier
@Retention(RUNTIME)
public @interface Diesel {
}

说明:只定义两个不同名称的注解即可,空实现即可,因为我们就是通过不同的注解区分Provides,以便让Component找到所要找的实例。记得导包:

import static java.lang.annotation.RetentionPolicy.RUNTIME;

4.2.2 修改EngineModule类:

@Module
public class EngineModule {

    @Provides
    @Gasloline
    public Engine provideGasoline(){
        return new GasolineEngline();
    }

    @Provides
    @Diesel
    public Engine provideDiesel(){
        return new DieselEngline();
    }
}

4.2.3 在Car类(父类)指定要采用哪个注解(即用哪个Provides):

public class Car {
    private Engine mEngine;

    @Inject
    public Car(@Gasloline Engine engine) {
        mEngine = engine;
    }
    public String run(){
        return mEngine.work();
    }
}
11-28 14:36:27.832 22846-22846/com.smartisan.dagger2 D/fukq: car---汽油发动机发动

5. @Singleton和@Scope

5.1 @Singleton

@Scope是用来自定义注解的,而@Singleton是用来配合实现局部单例和全局单例的。注意:@Singleton本身不具备创建单例的能力。我们从示例来分析

    @Inject
    Gson mGson;
    @Inject
    Gson mGson2;

    Log.d("fukq",mGson.hashCode()+"");
    Log.d("fukq",mGson2.hashCode()+"");

    210706522
    73949835

上面是两个Gson的实例,分别是mGson和mGson2,打印了两个实例的内存地址,内存地址不同说明它们不是一个对象,那如果我们想让Gson在MainActivity中是单例,咋弄呢?这个时候@Singleton就派上用场了。

5.1.1 修改GsonModule,添加@Singleton:

@Module
public class GsonModule {
    
    @Singleton
    @Provides
    public Gson provideGson(){
        return new Gson();
    }
}

5.1.2 在MainActivityComponent中添加@Singleton:

@Singleton
@Component(modules = {GsonModule.class,EngineModule.class})
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

我们再次打印两个Gson对象的内存地址值,结果如下:

11-28 15:32:39.425 25927-25927/? D/fukq: 73949835
11-28 15:32:39.425 25927-25927/? D/fukq: 73949835

说明:这个时候我们发现Gson在MainActivity中是单例,那么我们再创建一个SecondActivity,SecondActivity创建的Gson的内存地址和MainActivity中的是一样的吗?答案是:肯定不一样。因为我们只在MainActivityComponent中添加@Singleton,意思是只在MainActivity中是单例的。那如何实现全局单例呢?我们创建一个全局的Component,也就是说Component保证只有一个实例。如何保证Component只有一个实例呢?我们在Application中初始化即可。

5.2 @Scope

我们看下@Singleton的源码:

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}

我们发现,它是用@Scope来修饰的。所以这里我们不用@Singleton来实现全局实例,我们用@Scope仿写一个:之所以仿写,一来可以清楚看到@Scope的作用,二来可以自定义注解的名称(总是叫Singleton,很单调)。

5.2.1 定义@ApplicationScope注解:

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationScope {
}

5.2.2 在GsonModule中使用@ApplicationScope:

@Module
public class GsonModule {

    @ApplicationScope
    @Provides
    public Gson provideGson(){
        return new Gson();
    }
}

5.2.3 创建ActivityComponent来处理多个Activity:

@ApplicationScope
@Component(modules = GsonModule.class)
public interface ActivityComponent  {
    void inject(MainActivity mainActivity);
    void inject(SecondActivity mainActivity);
}

5.2.4 创建App类继承Application,用来提供ActivityCompenent实例:

public class App extends Application {
    
    ActivityComponent mActivityComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        mActivityComponent = DaggerActivityComponent.builder().build();
    }
    
    public static App get(Context context){
        return (App) context.getApplicationContext();
    }
    
    ActivityComponent getActivityComponent(){
        return mActivityComponent;
    }
}

5.2.5 使用全局的Component来注入Gson:

public class MainActivity extends AppCompatActivity {
    @Inject
    Gson mGson;
    @Inject
    Gson mGson2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        App.get(MainActivity.this).getActivityComponent().inject(this);
        Log.d("fukq:MainActivity",mGson.hashCode()+"");
        Log.d("fukq:MainActivity",mGson2.hashCode()+"");
        findViewById(R.id.bt_skip_to_second).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,SecondActivity.class));
            }
        });
    }
}
public class SecondActivity extends AppCompatActivity {

    @Inject
    Gson mGson;
    @Inject
    Gson mGson2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setContentView(R.layout.activity_main);

        App.get(SecondActivity.this).getActivityComponent().inject(this);
        Log.d("fukq:SecondActivity",mGson.hashCode()+"");
        Log.d("fukq:SecondActivity",mGson2.hashCode()+"");
    }
}
11-28 17:06:28.703 29041-29041/? D/fukq:MainActivity: 150530801
    150530801
11-28 17:06:44.454 29041-29041/com.smartisan.dagger2 D/fukq:SecondActivity: 150530801
11-28 17:06:44.454 29041-29041/com.smartisan.dagger2 D/fukq:SecondActivity: 150530801

说明:
① 发现MainActivity和SecondActivity中的Gson的内存地址一样,也就是实现了Gson的全局单例。
② 利用@Scope可以更好地管理Component和Module之间的匹配关系。比如编译器会检查Component管理的Module,若发现管理的Module中的标注创建实例方法的Scope注解与Component中的Scope注解不一致,就会报错。
③ 一般来说会有一个全局的Component,每个界面有自己的Component,当然不是必需,如果页面之间的依赖的类是一样的,可以共用一个Component。

6. @Component的dependencies

@Component可以用dependencies依赖于其他Component。这里我们让ActivityComponent依赖SuperComponent。

6.1 创建类SuperMan:

public class SuperMan {
    
    @Inject
    public SuperMan() {
    }
    
    public String fighting(){
        return "欲为大树,莫与草争";
    }
}

6.2 创建SuperModule和SuperComponent:

@Module
public class SuperManModule {

    @Provides
    public SuperMan provideSuperMan(){
        return new SuperMan();
    }
}
@Component(modules = SuperManModule.class)
public interface SuperManComponent {
    SuperMan getSuperMan();
}

6.3 在ActivityComponent中引入SuperManComponent:

@ApplicationScope
@Component(modules = GsonModule.class,dependencies = SuperManComponent.class)
public interface ActivityComponent  {
    void inject(MainActivity mainActivity);
    void inject(SecondActivity mainActivity);
}

注意:每次更新Component记得编译下,对应As的小锤子。

6.4 在此前定义的App类中引入SuperManComponent,修改App代码:

public class App extends Application {

    ActivityComponent mActivityComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        mActivityComponent = DaggerActivityComponent.builder().superManComponent(DaggerSuperManComponent.builder().build()).build();
    }

    public static App get(Context context){
        return (App) context.getApplicationContext();
    }

    ActivityComponent getActivityComponent(){
        return mActivityComponent;
    }
}

说明:可以对照之前App的代码,不难发现,只是对ActivityComponent的生成进行修改,修改后可以体现出来SuperManComponent和ActivityComponent的依赖关系。

6.5 在MainActivity中使用SuperMan:

public class MainActivity extends AppCompatActivity {
    @Inject
    SuperMan mSuperMan;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        App.get(MainActivity.this).getActivityComponent().inject(this);
        String str = mSuperMan.fighting();
        Log.d("fukq", "onCreate: str" + str);
    }
}
11-29 11:36:27.348 10510-10510/com.smartisan.dagger2 D/fukq: onCreate: str欲为大树,莫与草争

7. 懒加载

Dagger2 提供了懒加载,就是在注入实例的时候不实例化,而是在使用的时候,调用get方法来 获取实例。修改SuperMan的注入,代码如下:

public class MainActivity extends AppCompatActivity {
    @Inject
    Lazy<SuperMan> mSuperManLazy;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        App.get(MainActivity.this).getActivityComponent().inject(this);
        SuperMan superMan = mSuperManLazy.get();
        String str = superMan.fighting();
        Log.d("fukq", "onCreate: str" + str);
    }
}
11-29 11:47:43.576 10925-10925/com.smartisan.dagger2 D/fukq: onCreate: str欲为大树,莫与草争

8. Dagger2 原理分析

因为Dagger2的应用场景比较多,我们这里进行原理分析,拿Person注入的例子,例子代码我再复制下,省去大家往前面翻:

public class Person{
    @Inject
    public Person() {
    }

    public void eat(){
        Log.i("fukq","我要吃面包");
    }
}
@Component
public interface MainActivityComponent {
    void inject(MainActivity mainActivity);
}
public class MainActivity extends AppCompatActivity {
    @Inject
    Person mPerson;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainActivityComponent.create().inject(this);
        mPerson.eat();
    }
}

8.1 看下核心代码

DaggerMainActivityComponent.create().inject(this);

说明:这里是核心代码,我们第一看create方法,第二看inject方法,看清楚两个方法的实现逻辑就能够明白Dagger的核心Component到底做了什么事情,也就能明白Dagger的实现原理。

public final class DaggerMainActivityComponent implements MainActivityComponent {
  private MembersInjector<MainActivity> mainActivityMembersInjector;

  private DaggerMainActivityComponent(Builder builder) {
    assert builder != null;
    initialize(builder); // 4
  }

  public static Builder builder() {
    return new Builder(); // 2
  }

  public static MainActivityComponent create() {
    return builder().build(); // 1
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create()); // 5
  }

  @Override
  public void inject(MainActivity mainActivity) {
    mainActivityMembersInjector.injectMembers(mainActivity); // 6
  }

  public static final class Builder {
    private Builder() {}

    public MainActivityComponent build() {
      return new DaggerMainActivityComponent(this); // 3
    }
  }
}

说明:
① Component就是Dagger核心逻辑所在,所以我们看DaggerMainActivityComponent做了什么。
② 一步一步看,由表及里:
先看create()方法,执行的是代码 1 处 :

public static MainActivityComponent create() {
    return builder().build(); // 1
  }

再看builder()方法:

public static Builder builder() {
    return new Builder(); // 2
  }

接着看build()方法:

public MainActivityComponent build() {
      return new DaggerMainActivityComponent(this); // 3
    }

代码3执行的DaggerMainActivityComponent的构造方法,并传入Builder对象:

private DaggerMainActivityComponent(Builder builder) {
    assert builder != null;
    initialize(builder);  // 4
  }

再接着看initialize()方法,拿到了MembersInjector对象,引用是mainActivityMembersInjector:

@SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create()); // 5
  }  

拿到mainActivityMembersInjector引用后,它干了点啥呢:

  @Override
  public void inject(MainActivity mainActivity) {
    mainActivityMembersInjector.injectMembers(mainActivity); // 6
  }

接着看injectMembers方法:

public interface MembersInjector<T> {

  /**
   * Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
   * absence of an injectable constructor.
   *
   * <p>Whenever the object graph creates an instance, it performs this injection automatically
   * (after first performing constructor injection), so if you're able to let the object graph
   * create all your objects for you, you'll never need to use this method.
   *
   * @param instance into which members are to be injected
   * @throws NullPointerException if {@code instance} is {@code null}
   */
  void injectMembers(T instance);
}

发现它是接口MembersInjector的方法,那谁实现了这个接口呢,点左边小原绿色图标:会发现是名为MainActivity_MembersInjector的类,这个名字好熟悉,原来往上退两步,就是代码 5:

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create()); // 5
  }

我们又看到了MainActivity_MembersInjector这类,那弄清楚它的类里面的injectMembers和create(Person_Factory.create())方法应该就能分析出来原理了,代码:

public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final Provider<Person> mPersonProvider;

  public MainActivity_MembersInjector(Provider<Person> mPersonProvider) {
    assert mPersonProvider != null;
    this.mPersonProvider = mPersonProvider;  // 2
  }

  public static MembersInjector<MainActivity> create(Provider<Person> mPersonProvider) {
    return new MainActivity_MembersInjector(mPersonProvider);  // 1
  }

  @Override
  public void injectMembers(MainActivity instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mPerson = mPersonProvider.get();
  }

  public static void injectMPerson(MainActivity instance, Provider<Person> mPersonProvider) {
    instance.mPerson = mPersonProvider.get();
  }
}

因为create方法先于injectMembers方法调用,我们先看create方法:

public static MembersInjector<MainActivity> create(Provider<Person> mPersonProvider) {
    return new MainActivity_MembersInjector(mPersonProvider);  // 1
  }

会发现调用了MainActivity_MembersInjector类的构造方法:

public MainActivity_MembersInjector(Provider<Person> mPersonProvider) {
    assert mPersonProvider != null;
    this.mPersonProvider = mPersonProvider;  // 2
  }

这个构造方法传进来的是什么呢?我们往上看

this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create());

会发现Person_Factory.create(),那这里做了什么呢?

public enum Person_Factory implements Factory<Person> {
  INSTANCE;

  @Override
  public Person get() {
    return new Person();
  }

  public static Factory<Person> create() {
    return INSTANCE;
  }
}

原来是一个枚举单例 create()方法,返回的是Person_Factory,但是MainActivity_MembersInjector的构造方法的参数是Provider<Person> mPersonProvider,和Person_Factory啥关系呢?怎么就可以直接传入了,看Person_Factory的超类Factory<Person>代码:

public interface Factory<T> extends Provider<T> {
}

原来Factory<Person>的超类是Provider<T>,怪不得可以直接传入呢。那现在我们看看传进来的这个参数Provider<Person> mPersonProvider 干了点啥呢:

@Override
  public void injectMembers(MainActivity instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mPerson = mPersonProvider.get();
  }

原来是在injectMembers方法中,这样正好不用额外去分析injectMembers方法了,instance是MainActivity的引用, instance.mPerson就是它的成员变量Person对象的引用mPerson,那有了引用了,等号右边是什么呢?

public enum Person_Factory implements Factory<Person> {
  INSTANCE;

  @Override
  public Person get() {
    return new Person();
  }

  public static Factory<Person> create() {
    return INSTANCE;
  }
}

往上看:看到了get方法的返回是

return new Person();

看到这里,我们发现讲了这么多,这3个辅助类的作用就是调用inject方法的时候,将新创建的Person实例赋值给MainActivity的成员变量Person。其中Person_Factory用来生产Person的实例,MainActivity_MembersInjector用来把Person的实例赋值给MainActivity的成员变量Person,而DaggerMainActivityComponent就是为了把两者给串联起来。而这就是Dagger的实现原理。
这里我们还看出了,单一职责原则和建造者设计模式的引用,建议平时多看看源码,会让我们受益匪浅。一起加油!

9. 后续

如果大家喜欢这篇文章,欢迎点赞;如果想看更多 Dagger 方面的技术,欢迎关注!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容