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(); }
@Module public 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 @Module public 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]
分析这里为什么会出现问题呢?
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 @Module public 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://www.f2er.com/javaschema/283856.html