Dagger 2 Activity 上下文/ApplicationContext 模块

Posted

技术标签:

【中文标题】Dagger 2 Activity 上下文/ApplicationContext 模块【英文标题】:Dagger 2 Activity context/ApplicationContext modules 【发布时间】:2015-11-01 02:19:26 【问题描述】:

为了了解如何根据需要传递上下文或其他上下文,我正在努力使用 Dagger 2。 - 首先我有一个 ApplicationModule 注释 @Singleton 因为它提供了像 webservice 对象、模型......这样的高级对象,通常这些对象通过 ApplicationContext (因为你需要在整个应用程序生命周期中都存在)

@Singleton
@dagger.Component(modules = 
    AppModule.class
)
public interface AppComponent 
        void inject(MyApp application);
        Model model();
        Context context();<--- should provide the application Context for the Object above (model)
...

实现看起来像这样

@dagger.Module
public class AppModule 

    private final Application app;
    public ApplModule(Application app) 
        this.app = app;
    

    @Provides
    @Singleton
    Model provideModel(Bus bus) 
        return new Model(bus);
    

    @Provides
    @Singleton
    Context provideApplicationContext() 
        return app.getApplicationContext();
    
...

其次,我有一个活动范围组件,我提供当前活动和需要上下文的不同视图。

  @ActivityScope
    @Component(
            dependencies = AppComponent.class
            , modules = ActivityModule.class
    )
    public interface ActivityComponent 
        void inject(MyActivity activity);
        Context context(); <---should provide the activity's context
        MyView homeView(); <----takes a Context as a contructor parameter

@模块 公共类 ActivityModule 私人最终Activity活动;

public ActivityModule(Activity activity) 

    this.activity = activity;


@Provides
@ActivityScope
public Activity activity() 
    return activity;



@Provides
@ActivityScope
@Named("viewcontext") <----- if I removed this I get an error from Dagger
public Context context() 
    return activity;


@Provides
@ActivityScope
MyView provideZeView(Bus bus, Model model)  <---- previously receiving the ApplicationContext as a parameter 
    MyView v = new MyView(activity, bus, model); <---- must pass the activity otherwise passing the Context reveived is the ApplicationContext
    return v;

所以这是我的问题:

我使用范围是为了对传递的内容有更好的“粒度”,但我仍然得到 applicationContext 如果我删除 @Named 限定符,我会收到错误消息 以前的视图是由另一个依赖于 ActivityModule 但仍获取 ApplicationContext 的模块生成的

关键是我肯定遗漏了一些东西......但我不知道是什么,也许我误解了 Scopes 的使用

【问题讨论】:

考虑到您有两个几乎相同的Context,您需要在它们上指定@Named("application")@Named("activity") 虽然实际上,您可以不添加 Context context() 到您的组件中,只添加到模块中,它也可以工作! 因为 Dagger 实现了基于类型的注入,该类型有两个提供 Context 类的方法可能会导致错误,这就是为什么好人包含 @Named() 注释的原因。 【参考方案1】:

如果您想从您的模块中提供多个相同类型的对象,则需要@Named

至于你的第二个问题,关于传递正确的 Activity 上下文,你需要在你的 ActivityComponent 中有这个:

Activity activity();

【讨论】:

【参考方案2】:

您可以使用这样的限定符。在两个单独的文件中定义以下内容:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityContext 


@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationContext 

然后在您的 ActivityModule 中执行以下操作:

@Provides
@ActivityScope
@ActivityContext
public Context context() 
    return activity;

同样在你的 appmodule 中这样做:

 @Provides
    @Singleton
@ApplicationContext
    Context provideApplicationContext() 
        return app.getApplicationContext();
    

现在我们可以根据限定符 @ApplicationContext 和 @ActivityContext 询问我们需要的任何类型的上下文。

例如,在您的活动中,您可以这样做:

  @Inject @ApplicationContext
    Context c;

这将注入一个应用程序上下文。

在一个模块中你可以这样做:

  @Provides
    @ActivityScope
    LoginPresenter provideLoginPresenter(@ActivityContext Context context) 
        return new LoginPresenter(context);
    

提供活动上下文。这只是一个例子。

【讨论】:

以上是关于Dagger 2 Activity 上下文/ApplicationContext 模块的主要内容,如果未能解决你的问题,请参考以下文章

Dagger 2 注入 Android 应用程序上下文

Dagger 2,在模块中提供应用程序上下文

使用 Dagger 2.x 注入 Singleton 类

浅析Dagger2的使用

Dagger 2 - 为啥我收到循环引用错误?

dagger2简单使用与理解笔记