Dagger2的依赖关系的分析和理解

来源:互联网 发布:北美免费海关数据 编辑:程序博客网 时间:2024/06/07 01:52

Student.java文件

public class Student {    private int age;    private String name;    public Student(int age, String name) {        this.age = age;        this.name = name;    }    public void setAge(int age) {        this.age = age;    }    public int getAge() {        return age;    }    public void setName(String name) {        this.name = name;    }    public String getName() {        return name;    }}

在appcomponent包下面,三个文件:AppComponent.java、AppModule.java、PerActivity.java。

AppComponent.java文件

@Singleton@Component(modules = AppModule.class)public interface AppComponent {    Context getApplicationContext();    Student getStudent();}


AppModule.java文件

@Modulepublic class AppModule {    private static int count = 0;    private App app;    public AppModule(App app) {        this.app = app;    }    @Provides    @Singleton    Student providerStudent() {        return new Student(23, "jack" + String.valueOf(count++));    }    @Provides    @Singleton    Context providerApplicationContext() {        return app.getApplicationContext();    }}


PerActivity.java文件

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


在包MainComponent包下的两个文件。

ConstructorComponent.java文件

@PerActivity@Component(modules = ConstructorModule.class)public interface ConstructorComponent {    void inject(MainActivity mainActivity);}

ConstructorModule.java文件
@PerActivity@Modulepublic class ConstructorModule {    public ConstructorModule() {    }}



public class App extends Application {    private AppComponent appComponent;    @Override    public void onCreate() {        super.onCreate();        appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();    }    public AppComponent getAppComponent() {        return appComponent;    }}


public class MainActivity extends AppCompatActivity {    Button btn;    @Inject    Student student;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btn = (Button) findViewById(R.id.btn);        DaggerConstructorComponent.builder().appComponent(((App)getApplication()).getAppComponent())                .constructorModule(new ConstructorModule()).build().inject(this);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                test();            }        });    }    private void test() {        Toast.makeText(getApplicationContext(), student.getName() + ", " + student.getAge(), Toast.LENGTH_SHORT).show();    }}


编译发生如下错误:
Error:(14, 10) 错误: com.robot.ddagger.bean.Student cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
com.robot.ddagger.MainActivity.student
[injected field of type: com.robot.ddagger.bean.Student student]

分析这里为什么会出现问题呢?

先看看在dagger2帮我们生成了哪些文件。

AppModule_ProviderApplicationContextFactory.java

AppModule_ProviderStudentFactory.java

DaggerAppComponent.java

MainActivity_MembersInjector.java // 生成这个文件是因为在MainActivity中有@Inject Student student;,如果去掉这句话则不会生成这个文件。


按照dagger2的规则应该也会对应生成,DaggerConstructorComponent.java文件,但是这里并没有生成。

看看错误的提示,翻译一下:不能没有一个@Inject构造函数或从@ Provides-提供或@产生注解方法。


不好理解,还是从生成的MainActivity_MembersInjector.java分析。

@Generated("dagger.internal.codegen.ComponentProcessor")public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {  private final MembersInjector<AppCompatActivity> supertypeInjector;  private final Provider<Student> studentProvider;  public MainActivity_MembersInjector(MembersInjector<AppCompatActivity> supertypeInjector, Provider<Student> studentProvider) {      assert supertypeInjector != null;    this.supertypeInjector = supertypeInjector;    assert studentProvider != null;    this.studentProvider = studentProvider;  }  @Override  public void injectMembers(MainActivity instance) {      if (instance == null) {      throw new NullPointerException("Cannot inject members into a null reference");    }    supertypeInjector.injectMembers(instance);    instance.student = studentProvider.get();  }  public static MembersInjector<MainActivity> create(MembersInjector<AppCompatActivity> supertypeInjector, Provider<Student> studentProvider) {        return new MainActivity_MembersInjector(supertypeInjector, studentProvider);  }}
可以看到这里有个Provider<Student> studentProvider;,也就是说MainActivity_MembersInjector.java需要这个studentProvider。

这里如果在MainActivity.java中有其他的@Inject XXX xxx,那么也会在MainActivity_MembersInjector.java中产生,Provider<XXX> xxxProvider。


我们也知道DaggerXXXComponent调用inject()函数的时候,将会调用相关的XXX_MembersInjector中的函数。

对应于这里的情况就是DaggerConstructorComponent中的inject()函数,会调用这里的MainActivity_MembersInjector中函数。

首先调用的当然是这里的MainActivity_MembersInjector中的create()了。


那么问题来了,这里的Provider<Student> studentProvider如何从

DaggerConstructorComponent传递给MainActivity_MembersInjector的create()呢?也就是说DaggerConstructorComponent必然自己也有

Provider<Student> studentProvider这个。回到我们的ConstructorComponent.java的定义。

@PerActivity@Component(modules = ConstructorModule.class)public interface ConstructorComponent {    void inject(MainActivity mainActivity);}


可以看到这里ConstructorComponent中至于ConstructorModule有关,再看看ConstructorModule的定义,发现它并没有提供什么。

@PerActivity@Modulepublic class ConstructorModule {    public ConstructorModule() {    }}


看到这里应该有点明白了吧。简单的理清一下思路。

(1)在MainActivity中的@Inject Student student,导致生成了MainActivity_MembersInjector,而且是构造函数带有参数Provider<Student>的。

(2)而我们定义的ConstructorComponent中可以知道,MainActivity是目标类,而ConstructorModule是目标依赖类。

生成的DaggerConstructorComponent的inject到时候会调用MainActivity_MembersInjector类,需要将Provider<Student>传递给

MainActivity_MembersInjector类,但是发现ConstructorModule并没有提供任何有关Provider<Student>的东西。


所以导致DaggerConstructorComponent生成不了。

解决方法也很简单,你需要告诉DaggerConstructorComponent,你提供了Provider<Student>了。

@PerActivity@Component(dependencies = AppComponent.class, modules = ConstructorModule.class)public interface ConstructorComponent {    void inject(MainActivity mainActivity);}


看看AppComponent的定义,已经提供了Student了。
@Singleton@Component(modules = AppModule.class)public interface AppComponent {    Context getApplicationContext();    Student getStudent();}

这样子DaggerConstructorComponent就可以把Provider<Student>传递给MainActivity_MembersInjector了。

看看生成的DaggerConstructorComponent.java文件:

@Generated("dagger.internal.codegen.ComponentProcessor")public final class DaggerConstructorComponent implements ConstructorComponent {  private Provider<Student> getStudentProvider;  private MembersInjector<MainActivity> mainActivityMembersInjector;  private DaggerConstructorComponent(Builder builder) {      assert builder != null;    initialize(builder);  }  public static Builder builder() {      return new Builder();  }  private void initialize(final Builder builder) {      this.getStudentProvider = new Factory<Student>() {      private final AppComponent appComponent = builder.appComponent;      @Override public Student get() {        Student provided = appComponent.getStudent();        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(), getStudentProvider);  }  @Override  public void inject(MainActivity mainActivity) {      mainActivityMembersInjector.injectMembers(mainActivity);  }  public static final class Builder {    private ConstructorModule constructorModule;    private AppComponent appComponent;      private Builder() {      }      public ConstructorComponent build() {        if (constructorModule == null) {        this.constructorModule = new ConstructorModule();      }      if (appComponent == null) {        throw new IllegalStateException("appComponent must be set");      }      return new DaggerConstructorComponent(this);    }      public Builder constructorModule(ConstructorModule constructorModule) {        if (constructorModule == null) {        throw new NullPointerException("constructorModule");      }      this.constructorModule = constructorModule;      return this;    }      public Builder appComponent(AppComponent appComponent) {        if (appComponent == null) {        throw new NullPointerException("appComponent");      }      this.appComponent = appComponent;      return this;    }  }}


重点代码,可以看到这里的studentProvider是AppComponent提供的。并且把studentProvider传递给MainActivity_MembersInjector了。
private void initialize(final Builder builder) {        this.getStudentProvider = new Factory<Student>() {            private final AppComponent appComponent = builder.appComponent;            @Override            public Student get() {                Student provided = appComponent.getStudent();                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(), getStudentProvider);    }


本文资源代码下载 :https://github.com/robotlife/DDaggerDepend



0 0
原创粉丝点击