Dagger 2范围说明

时间:2016-04-01 07:16:06

标签: android dependency-injection scope dagger dagger-2

首先,我是新手,刚刚开始探索匕首,我有一些理解上的问题,所以希望有人可以帮助我。

我已经阅读了很多关于匕首的内容,但仍然无法找出一些部分。

我创建了ApplicationComponent,看起来像这样

@Singleton
@Component(modules = {
        ApplicationModule.class,
        ThreadingModule.class,
        NetworkModule.class,
        DatabaseModule.class,
        ServiceModule.class,
        ParseModule.class,
        PreferencesSessionModule.class})

public interface ApplicationComponent {
    void inject(BaseActivity baseActivity);
    void inject(MainAppActivity mainAppActivity);
    void inject(BaseFragment baseFragment);
}

它可以很好地正常注入,但现在我想更深入地研究dagger API并使用Custom Scope

我有一个名为PermissionModule的模块,它用于Android M版本。

@PerActivity
@Module
public class PermissionModule {
    @Provides
    @PerActivity
    PermissionController providePermissionController(Activity activity) {
        return new PermissionManager(activity);
    }
}

我希望将它注入我的活动并且只有当活动也在内存中时才会在内存中(活动生命周期)

@PerActivity
@Component(modules = {
        ActivityModule.class,
        PermissionModule.class
})
public interface ActivityComponent {
    Activity activity();

    void inject(BaseActivity baseActivity);

    PermissionModule permissionModule();
}

我的ActivityComponent

@PerActivity
@Component(modules = {
        ActivityModule.class,
        PermissionModule.class
})
public interface ActivityComponent {
    Activity activity();

    void inject(BaseActivity baseActivity);

    PermissionModule permissionModule();
}

我的BaseActivity

public abstract class BaseActivity extends AppCompatActivity implements SpiceManagerProvider, NetworkRequestsExecutor {
    // Dependencies are injected by ApplicationComponent
    @Inject
    protected ApplicationSettingsManager mApplicationSettingsManager;
    @Inject
    protected SpiceManager mSpiceManager;
    @Inject
    protected ScheduledThreadPoolExecutor mPoolExecutor;

    !!!!!!
    Should be injected by activity component 
    @Inject
    protected PermissionController mPermissionController;

并在onCreate()

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Injecting dependencies
        MyApplication application = MyApplication.get(this);
        application.getApplicationComponent().inject(this);
        DaggerActivityComponent.builder().activityModule(new ActivityModule(this)).build().inject(this);
        mPermissionController.requestPermission(Manifest.permission.ACCESS_FINE_LOCATION);
        mPermissionController.requestPermission(Manifest.permission.CAMERA);
        super.onCreate(savedInstanceState);
    }

我收到了错误

  

如果没有@ Provide-或者,则无法提供PermissionController   @ Produces-annotated方法。   .ui.activities.base.BaseActivity.mPermissionController

我的代码有什么问题?

也不要创建新问题,而且与此主题相关。

dagger2如何解析Scope注释,我无法弄清楚这一点。据我所知,匕首只识别Singleton注释,而所有其他注释都不会影响匕首决定,因为所有其他注释都有活动范围?

3 个答案:

答案 0 :(得分:0)

所以问题是你先调用ApplicationComponent的inject方法

application.getApplicationComponent().inject(this);

尝试注入所有成员,包括PermissionController。但是ApplicationComponent不能提供这个,这就是Dagger所抱怨的。

解决方案是只调用ActivityComponent的inject()方法。

很可能你确实需要ApplicationComponent在某些时候提供的依赖项。要归档它,您需要组合这两个组件。 Dagger为此提供了两种方式,subcomponentscomponent dependencies

使用组件依赖时,在Activity的onCreate()方法中,rou最终将会出现类似的内容:

 DaggerActivityComponent
            .builder()
            .applicationComponent(application.getApplicationComponent())
            .activityModule(new ActivityModule(this))
            .build().inject(this);

当您更改组件以查找类似于此的组件时:

@PerActivity
@Component(
    dependencies = ApplicationComponent.class, 
    modules = {
        ActivityModule.class,
        PermissionModule.class
    }
)
public interface ActivityComponent {
    ...
}

请注意,在ActivityComponent(或任何注入器)中需要时,需要在ApplicationComponent中显式提供依赖项

答案 1 :(得分:0)

如果要在子组件中使用父组件(例如@Componenet(model = AppModel.class)public interface appComponent ...)的任何依赖项(@ActivityScope @Component(DEPENDENCY = APPCOMPONENT.class, model = ActivityModel.class)public interface activityComponenet ...)您需要在父组件中公开它。只有暴露的依赖项可以在下游访问(在子组件中)。您可以通过从appModel编写需要在appComponenet接口中提供下游依赖性的方法来实现。方法的名称不需要与appModel中的方法名称匹配,只需要返回类型计数。

答案 2 :(得分:-1)

关于你对Dagger范围的困惑,我特此指出关于范围的一些结论

  • 如果同一组件注入了无范围的服务,则会创建一个新的服务实例。
  • 第一次注入@Singleton作用域服务时,它会在注入组件中实例化并缓存,然后在同一组件注入相同类型的其他字段时将使用相同的实例。
  • 自定义用户定义的范围在功能上等同于预定义的@Singleton Scope
  • 注入范围服务是线程安全的。

如果您真的想清楚地了解Dagger内部如何使用单身和自定义范围,请按照本文Dagger 2 Scopes : How It Works Internally