java - Android 上的 Dagger 2。存储和访问 @Singleton 组件的不同方式

标签 java android dagger-2

这是关于如何存储生命周期应等于应用程序生命周期的@Singleton 作用域 Dagger 2 组件的第 N 个问题。

在使用 Dagger 2 的 Android 应用程序中,通常至少有一个 Component 是 @Singleton 范围的,并且应该在应用程序的整个生命周期中持续存在:由于这些要求,它通常被初始化并存储在自定义 Application 类中。

因为这个组件的实例必须在我们应用程序的所有部分都可以访问,所以我见过这样的代码:

1。将组件存储在应用程序类内的公共(public)静态变量中。

public class App extends Application {

    public static AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this)).build();
    }
}

这样就可以在其他任何地方访问:

App.appComponent.inject(this);

2。将组件存储在应用程序实例内的私有(private)变量中,并为其创建静态访问器。

public class App extends Application {

    private static AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this)).build();
    }

    public static AppComponent getAppComponent() {
        return appComponent;
    }
}

这样就可以在其他任何地方访问:

App.getAppComponent().inject(this);

3。将组件存储在应用程序实例内的私有(private)变量中,并为其创建一个非静态访问器。

public class App extends Application {

    private AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this)).build();
    }

    public AppComponent getAppComponent() {
        return appComponent;
    }
}

这样它只能从持有对 Context 的引用的类实例访问:

// From within an Activity.
((App) getApplication()).getAppComponent().inject(this);

// From within a Fragment.
((App) getActivity().getApplication()).getAppComponent().inject(this);

// From within any other class which holds a reference to a Context. 
((App) context.getApplicationContext()).getAppComponent().inject(this);

最后一种方式使得将 Context 引用传递给任何愿意访问组件的类变得非常强制(即使该类出于任何其他目的不需要该 Context)。

恕我直言,必须“手动注入(inject)”一个 Context 实例才能访问注入(inject)器本身,这听起来有点违反直觉。

另一方面,许多人建议不要使用静态变量,但是:为什么?如果一个对象必须在应用程序的生命周期(这意味着 JVM 实例的整个生命周期)内保留在内存中,如果它存储在静态变量中会有什么问题?

其他人说静态的东西不能在测试中被模拟,这是真的,虽然我不确定我完全理解这个,因为它是 DI 模式,而不是注入(inject)器本身,它可以轻松模拟/测试,所以为什么会我们想模拟注入(inject)器本身吗?

这些替代方案的优缺点是什么?除了这里已经提到的之外,还有其他可能的替代方案吗?

最佳答案

对于 1 和 2,您使用的是静态引用。这是一个关于为什么要避免它们的好帖子

Why are static variables considered evil?

所以剩下的唯一选择就是第三个。这就是我在我的项目中使用的。 关于是否应该将上下文作为参数传递,取决于项目的体系结构以及设计 Dagger 依赖项的方式。我个人没有这个问题,因为我只注入(inject) Activity/fragment 。你能给我一个例子,你需要传递上下文来注入(inject)依赖吗?

关于java - Android 上的 Dagger 2。存储和访问 @Singleton 组件的不同方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39264599/

相关文章:

java - Jar 文件找不到图像目录

java - 当预览打开时,Android SurfaceView 叠加在相机 View 上不显示

android - 异常 : OutOfMemoryError

java - Dagger 2 问题覆盖单个提供来自应用程序使用的库中模块的注释方法

java - Dagger 2 : Using factory methods in place of public constructors

java - 是否可以将java类对象序列化为类文件?

java - 比较时间戳与实际时间(Java)

android - Android TextView 到图像文件?

android - 同一个项目中的 Realm.io/Dagger/Databinding

java - 如何安装 TestFX?