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();}
@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(); }}
@Scope@Retention(RetentionPolicy.RUNTIME)public @interface PerActivity {}
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);}
@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);}
@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
- Dagger2的依赖关系的分析和理解
- Dagger2依赖关系分析
- 安卓开发 第一篇 关于依赖注入框架dagger2的使用和理解
- 第一篇 关于依赖注入框架dagger2的使用和理解
- 设计-依赖关系的理解
- Dagger2自己的理解
- 分析数据库的依赖关系
- Dagger2----一个最简单的Dagger2依赖的实现
- 一些关于dagger2的理解
- 我所理解的Dagger2
- 我所理解的Dagger2
- dagger2框架的学习理解
- 我对Dagger2的理解
- 依赖关系和关联关系的区别
- 关联关系和依赖关系的思考
- 依赖注入库 Dagger2 的使用方法
- Dagger2的组件依赖及使用详解
- Dagger2-Android依赖注入框架的学习
- spring(5)构建 spring web 应用程序
- matlab之plot、fplot、ezplot函数
- [从头学数学] 第237节 重积分
- spring源码解析
- 操作linux redis 常用命令
- Dagger2的依赖关系的分析和理解
- iOS多级跳转,返回指定viewcontroller
- js date 操作
- tcp标志push与发送窗口的关系
- 如何用#define宏定义多行函数
- Ubuntu16.04 安装flash player
- SQL Server优化50法
- sql语句基础要点(以sql server 2008 为例)
- 选择排序和插入排序