This tutorial在一个非常简单的示例中展示了如何使用 Dagger 2 的 AndroidInjectionModule
将依赖项注入(inject) Activity 。我的用例有点复杂:
App extends Application implements HasDispatchingActivityInjector
,ActivityOne
使用ActivityModule
进行初始化。使用此 Activity ,创建依赖项DepOne
,ActivityTwo
具有依赖项DepTwo
,如果没有预先存在的DepOne
则无法正确初始化。
我想到的解决方案是:
- 创建一个
AppComponent
作为应用的主要组件, - 创建一个
ComponentTwo
作为AppComponent
的子组件。在运行时添加它,只要DepOne
可用,并在其中提供DepTwo
, - 在
ComponentTwo
中注入(inject)ActivityTwo
。
然而,这需要 ActivityModule
,目前看起来是这样的:
@Module(subcomponents = {
ActivityOneSubcomponent.class,
ActivityTwoSubcomponent.class
})
public abstract class ActivityModule {
@Binds
@IntoMap
@ActivityKey(ActivityOne.class)
abstract AndroidInjector.Factory<? extends Activity> bindLoginActivityInjectorFactory(ActivityOneSubcomponent.Builder builder);
@Binds
@IntoMap
@ActivityKey(ActivityTwo.class)
abstract AndroidInjector.Factory<? extends Activity> bindWorldActivityInjectorFactory(ActivityTwoSubcomponent.Builder builder);
}
分成两个不同的模块,一个用于 ActivityOne
并与 AppComponent
绑定(bind),另一个用于 ActivityTwo
(以及其他 future Activity ) 与 ComponentTwo
绑定(bind)。
我这样做了,但是 Dagger 在尝试注入(inject) ActivityTwo
时在运行时抗议:
Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class<ActivityTwo>
应用程序似乎看不到添加的子组件提供的注入(inject)器工厂。
有什么想法/提示吗?
编辑:我根据要求在下面发布了重现代码(那里实际上没有 Dagger 可注入(inject)的属性,因为我把它们刮掉了):
ActivityOne.java
public class ActivityOne extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
enterPartTwo();
}
private void enterPartTwo() {
App.app(this).makeComponentTwo();
ActivityTwo.start(this);
finish();
}
}
ActivityOneModule.java
@Module(subcomponents = {
ActivityOneSubcomponent.class
})
public abstract class ActivityOneModule {
@Binds
@IntoMap
@ActivityKey(ActivityOne.class)
abstract AndroidInjector.Factory<? extends Activity> bindActivityOneInjectorFactory(ActivityOneSubcomponent.Builder builder);
}
ActivityOneSubcomponent.java
@Subcomponent
public interface ActivityOneSubcomponent extends AndroidInjector<ActivityOne> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<ActivityOne> {}
}
ActivityTwo.java
public class ActivityTwo extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_world);
}
public static void start(Context from) {
Intent intent = new Intent(from, ActivityTwo.class);
from.startActivity(intent);
}
}
ActivityTwoModule.java
@Module(subcomponents = {
ActivityTwoSubcomponent.class
})
public abstract class ActivityTwoModule {
@Binds
@IntoMap
@ActivityKey(ActivityTwo.class)
abstract AndroidInjector.Factory<? extends Activity> bindActivityTwoInjectorFactory(ActivityTwoSubcomponent.Builder builder);
}
ActivityTwoSubcomponent.java
@Subcomponent
public interface ActivityTwoSubcomponent extends AndroidInjector<ActivityTwo> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<ActivityTwo> {}
}
App.java
public class App extends Application implements HasDispatchingActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
AppComponent appComponent;
ComponentTwo componentTwo;
@Override
public void onCreate() {
super.onCreate();
appComponent = DaggerAppComponent.create();
appComponent.inject(this);
}
@Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
public void makeComponentTwo() {
componentTwo = appComponent.inGameComponent()
.build();
}
public static App app(Context context) {
return (App) context.getApplicationContext();
}
}
AppComponent.java
@Singleton
@Component(modules = {ActivityOneModule.class,
AndroidInjectionModule.class})
public interface AppComponent {
void inject(App app);
ComponentTwo.Builder inGameComponent();
}
ComponentTwo.java
@ScopeTwo
@Subcomponent(modules = {ActivityTwoModule.class})
public interface ComponentTwo {
@Subcomponent.Builder
interface Builder {
ComponentTwo build();
}
}
ScopeTwo.java
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ScopeTwo {
}
堆栈跟踪:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.abc, PID: 5923
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.abc/com.example.abc.ActivityTwo}: java.lang.IllegalArgumentException: No injector factory bound for Class<com.example.abc.ActivityTwo>
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class<com.example.abc.ActivityTwo>
at dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:105)
at dagger.android.AndroidInjection.inject(AndroidInjection.java:61)
at com.example.abc.ActivityTwo.onCreate(ActivityTwo.java:22)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
希望对回答问题有所帮助。
最佳答案
让 ActivityTwo 实现 HasSupportFragmentInjector
public class ActivityTwo extends AppCompatActivity implements HasSupportFragmentInjector {
@Inject
DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
@Inject
DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return fragmentDispatchingAndroidInjector;
}
} // end of class
其次,对于小型实现而言,您的样板代码太多了。使用@ContributesAndroidInjector 为您的 Activity 创建子组件。使用这篇文章可以最简单地实现此 https://medium.com/@idee4ril/dagger-2-11-with-android-a606c132826c
关于android - Dagger 2 : Injecting to Activities from multiple subcomponents,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43952252/