当前位置 : 主页 > 手机开发 > 其它 >

dagger-2 – Dagger 2.11 ContributesAndroidInjector Singleton依赖注入失败

来源:互联网 收集:自由互联 发布时间:2021-06-22
我正在从Dagger 2.11中探索新的dagger. android.我希望不必像@PerActivity那样创建自定义范围注释.到目前为止,我能够做到以下几点: 1)定义应用程序范围单例并将它们注入活动. 2)使用@Contribu
我正在从Dagger 2.11中探索新的dagger. android.我希望不必像@PerActivity那样创建自定义范围注释.到目前为止,我能够做到以下几点:

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.

网友评论