1)定义应用程序范围单例并将它们注入活动.
2)使用@ContributesAndroidInjector定义活动范围非单例依赖关系并将它们注入到它们的活动中
我无法弄清楚的是如何使用它的应用程序范围Singleton和Activity范围非单例.
在下面的示例中,我希望我的活动范围MyActivityDependencyA和MyActivityDependencyB可以访问Singleton MyActivityService
以下设置导致:
Error:(24, 3) error: com.example.di.BuildersModule_BindMyActivity.MyActivitySubcomponent
(unscoped) may not reference scoped bindings:
@Singleton @Provides com.example.MyActivityService
com.example.MyActivitySingletonsModule.provideMyActivityService()
这是我的设置.注意,我定义了单独的MyActivitySingletonsModule和MyActivityModule,因为我无法在同一个Module文件中混合使用Singleton和非Singleton依赖项.
@Module public abstract class BuildersModule { @ContributesAndroidInjector(modules = {MyActivitySingletonsModule.class, MyActivityModule.class}) abstract MyActivity bindMyActivity(); } }
和
@Module public abstract class MyActivityModule { @Provides MyActivityDependencyA provideMyActivityDependencyA(MyActivityService myActivityService){ return new MyActivityDependencyA(myActivityService); } @Provides MyActivityDependencyB provideMyActivityDependencyB(MyActivityService myActivityService) { return new MyActivityDependencyB(myActivityService); } }
和
@Module public abstract class MyActivitySingletonsModule { @Singleton @Provides MyActivityService provideMyActivityService() { return new MyActivityService(); } }
和
@Singleton @Component(modules = { AndroidSupportInjectionModule.class, AppModule.class, BuildersModule.class}) public interface AppComponent { @Component.Builder interface Builder { @BindsInstance Builder application(App application); AppComponent build(); } void inject(App app); }
在没有定义自定义范围注释的情况下,甚至可以做我想做的事情吗?
提前致谢!
为什么要避免自定义范围? Dagger 2.10中引入的新dagger.android依赖注入框架仍然需要自定义范围.“My understanding is
@ContributesAndroidInjector
removes the need for custom annotation and I was able to prove it by using non-singletons defined in the activity scope without any issues.”
@ContributesAndroidInjector(在v2.11中提供)不会消除对自定义作用域的需要.它只是取代了声明@Subcomponent类的需要,这些类不使用@ Subcomponent.Builder来注入组件在运行时所需的依赖项.看一下official dagger.android user guide about @ContributesAndroidInjector
的下面片段;
“Pro-tip: If your subcomponent and its builder have no other methods or supertypes than the ones mentioned in step #2, you can use @ContributesAndroidInjector to generate them for you. Instead of steps 2 and 3, add an abstract module method that returns your activity, annotate it with @ContributesAndroidInjector, and specify the modules you want to install into the subcomponent. If the subcomponent needs scopes, apply the scope annotations to the method as well.”
@ActivityScope @ContributesAndroidInjector(modules = { /* modules to install into the subcomponent */ }) abstract YourActivity contributeYourActivityInjector();
这里的关键是“如果子组件需要范围,也可以将范围注释应用于方法.”
请查看以下代码,以了解如何将@Singleton,@ PerActivity,@ PerFragment和@PerChildFragment自定义作用域与新的dagger.android注入框架一起使用.
// Could also extend DaggerApplication instead of implementing HasActivityInjector // App.java public class App extends Application implements HasActivityInjector { @Inject AppDependency appDependency; @Inject DispatchingAndroidInjector<Activity> activityInjector; @Override public void onCreate() { super.onCreate(); DaggerAppComponent.create().inject(this); } @Override public AndroidInjector<Activity> activityInjector() { return activityInjector; } } // AppModule.java @Module(includes = AndroidInjectionModule.class) abstract class AppModule { @PerActivity @ContributesAndroidInjector(modules = MainActivityModule.class) abstract MainActivity mainActivityInjector(); } // AppComponent.java @Singleton @Component(modules = AppModule.class) interface AppComponent { void inject(App app); } // Could also extend DaggerActivity instead of implementing HasFragmentInjector // MainActivity.java public final class MainActivity extends Activity implements HasFragmentInjector { @Inject AppDependency appDependency; // same object from App @Inject ActivityDependency activityDependency; @Inject DispatchingAndroidInjector<Fragment> fragmentInjector; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); if (savedInstanceState == null) { addFragment(R.id.fragment_container, new MainFragment()); } } @Override public final AndroidInjector<Fragment> fragmentInjector() { return fragmentInjector; } } // MainActivityModule.java @Module public abstract class MainActivityModule { @PerFragment @ContributesAndroidInjector(modules = MainFragmentModule.class) abstract MainFragment mainFragmentInjector(); } // Could also extend DaggerFragment instead of implementing HasFragmentInjector // MainFragment.java public final class MainFragment extends Fragment implements HasFragmentInjector { @Inject AppDependency appDependency; // same object from App @Inject ActivityDependency activityDependency; // same object from MainActivity @Inject FragmentDependency fragmentDepency; @Inject DispatchingAndroidInjector<Fragment> childFragmentInjector; @SuppressWarnings("deprecation") @Override public void onAttach(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // Perform injection here before M, L (API 22) and below because onAttach(Context) // is not yet available at L. AndroidInjection.inject(this); } super.onAttach(activity); } @Override public void onAttach(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Perform injection here for M (API 23) due to deprecation of onAttach(Activity). AndroidInjection.inject(this); } super.onAttach(context); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.main_fragment, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (savedInstanceState == null) { addChildFragment(R.id.child_fragment_container, new MainChildFragment()); } } @Override public final AndroidInjector<Fragment> fragmentInjector() { return childFragmentInjector; } } // MainFragmentModule.java @Module public abstract class MainFragmentModule { @PerChildFragment @ContributesAndroidInjector(modules = MainChildFragmentModule.class) abstract MainChildFragment mainChildFragmentInjector(); } // MainChildFragment.java public final class MainChildFragment extends Fragment { @Inject AppDependency appDependency; // same object from App @Inject ActivityDependency activityDependency; // same object from MainActivity @Inject FragmentDependency fragmentDepency; // same object from MainFragment @Inject ChildFragmentDependency childFragmentDepency; @Override public void onAttach(Context context) { AndroidInjection.inject(this); super.onAttach(context); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.main_child_fragment, container, false); } } // MainChildFragmentModule.java @Module public abstract class MainChildFragmentModule { } // PerActivity.java @Scope @Retention(RetentionPolicy.RUNTIME) public @interface PerActivity { } // PerFragment.java @Scope @Retention(RetentionPolicy.RUNTIME) public @interface PerFragment { } // PerChildFragment.java @Scope @Retention(RetentionPolicy.RUNTIME) public @interface PerChildFragment { } // AppDependency.java @Singleton public final class AppDependency { @Inject AppDependency() { } } // ActivityDependency.java @PerActivity public final class ActivityDependency { @Inject ActivityDependency() { } } // FragmentDependency.java @PerFragment public final class FragmentDependency { @Inject FragmentDependency() { } } // ChildFragmentDependency.java @PerChildFragment public final class ChildFragmentDependency { @Inject ChildFragmentDependency() { } }
有关使用@ContributesAndroidInjector和上述自定义范围的完整dagger.android 2.11设置指南,请阅读this article.