Dagger2学习之Module的应用(二)

0x00.前言

Dagger2学习之配置和基础使用(一)中展示了最基本的Dagger2的应用。
在实际开发中有可能会出现两种情况,使用现在所掌握的技术手段是无法解决的。

1.有的时候有可能使用第三方的jar包。但是我们不可能在第三方jar包上写”@Inject”
2.构造函数可能需要传入参数。
正对以上的情况”@Module”就横空出世了。

0x01.Module类的应用

Module类:

@Module
public class ActivityModule {

    @Provides
    public User provideUser() {
        return new User();
    }
}

Module类实现起来很简单,在实现好的实体类上加上”@Module”和”@Provides”。它本质上是一个工厂类。这个类替代了在文章Dagger2学习之配置和基础使用(一)中在User类的构造函数上的”@Inject”,那为什么要使用这个Module类来替代呢?
聪明的你一定知道是为了解决文章开头的那两个问题。解决的重点是”@Provides”和对应的provideUser方法。这样,无论是第三方框架还是自己写的代码,都可以放到”provideUser”中去。那么需要通过构造函数传递参数该怎么办?当然有办法,我们只需要在”provideUser”方法上传入参数类似下面的代码:

@Provides
public User provideUser(int age) {
   return new User(age);
}

// 或者这样
@Provides
public User provideUser(int age) {
   User user = new User();
   user.setAge(age);
   return user;
}
// 这样可以覆盖所有需要传入参数的场景

当然,如果仅仅这样还是不行的。因为很明显,这里的方法参数是在哪里传入的呢,它并不是凭空出现的。
这里先给出Component代码:

@Component
public interface ActivityComponent {
    void inject(MainActivity daggerActivity);
}

注入到MainActivity的代码

public class MainActivity extends AppCompatActivity {
    //注入
    @Inject
    User user;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (TextView) findViewById(R.id.text);
        inject();
        Log.v("tag", "user.name::"+user.name);
    }

    //注入行为
    private void inject() {
        DaggerActivityComponent.create().inject(MainActivity.this);
    }

上面不是提到的参数是如何传入的呢?其实只需要改造下

DaggerActivityComponent.create().inject(MainActivity.this);

代码即可,代码如下:

DaggerActivityComponent.builder()
                .activityModule(new ActivityModule(23))// 在这里传入需要的参数
                .build()
                .inject(this);

这样,就彻底的解决了上面的两个问题。

0x02.关于Component

上一篇文章由于只是介绍最基本应用,没有介绍Component。那么在这里介绍下Component。
正如前面一篇文章说的。Component可以看成是医生使用的注射器,也可以看成是一个连接注入类和目标类的一个连接。

基本用法

首先新建立一个java接口,在接口上加上@Component。再在接口中提供一个抽象方法即可。

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

当然以上的代码是最简单的一种。
在使用了Module之后,需要在@Component通过”modules”来注明,你使用的是哪个Module。

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

这样就可以在注入类和目标类建立一个联系。虽然这里实现了一个接口,但是实际上是通过dagger插件,生成java代码。生成的部分代码如下(上面已经加了注释):

/**
 *DaggerActivityComponent实现ActivityComponent
 *这里采用了类似构建者模式
 */
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerActivityComponent implements ActivityComponent {
  private Provider provideUserProvider;
  private MembersInjector mainActivityMembersInjector;

  private DaggerActivityComponent(Builder builder) {  
    assert builder != null;
    initialize(builder);
  }

  // 返回Builder类
  public static Builder builder() {  
    return new Builder();
  }

  // 初始化
  private void initialize(final Builder builder) {  
    this.provideUserProvider = new Factory() {
      private final AppComponent appComponent = builder.appComponent;
      @Override public User get() {
        User provided = appComponent.provideUser();
        if (provided == null) {
          throw new NullPointerException("Cannot return null from a non-@Nullable component method");
        }
        return provided;
      }
    };
    this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideUserProvider);
  }

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

  // 最重要的Builder,构建者
  public static final class Builder {
    private ActivityModule activityModule;
    private AppComponent appComponent;

    private Builder() {  
    }
    // 返回ActivityComponent对象。
    // 同时,在构造函数中传入Builder对象。
    public ActivityComponent build() {  
      if (activityModule == null) {
        throw new IllegalStateException("activityModule must be set");
      }
      if (appComponent == null) {
        throw new IllegalStateException("appComponent must be set");
      }
      return new DaggerActivityComponent(this);
    }
     // 传入的ActivityModule参数
    public Builder activityModule(ActivityModule activityModule) {  
      if (activityModule == null) {
        throw new NullPointerException("activityModule");
      }
      this.activityModule = activityModule;
      return this;
    }
    // ................
  }
}

你可能感兴趣的:(android学习,dagger2,dagger2学习)