【问题标题】:Prevent Dagger2 component from recreating on screen rotation防止 Dagger2 组件在屏幕旋转时重新创建
【发布时间】:2017-12-03 17:26:20
【问题描述】:

我是 Dagger2 依赖注入的新手。当屏幕旋转时,我很难保留相同的组件。

@Inject
MainActivityPresenterImpl presenter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    component = DaggerMainActivityComponent.builder()
            .mainActivityModule(new MainActivityModule(this))
            .applicationComponent(TrainningDagger3.get(this).getComponent())
            .build();
    component.inject(this);
    presenter.fetchData();
}

我尝试调试应用程序,我认为当加载新配置时,它会创建组件的新实例和演示者的新实例。屏幕旋转时如何保留相同的组件和演示者。非常感谢!

【问题讨论】:

  • 必须重新创建组件,因为您将 Activity 添加到它。如果您尝试保留/存储组件,.mainActivityModule(new MainActivityModule(this)) 将添加 Activity 和 leak。我建议您阅读更多有关 Dagger 的教程,并熟悉人们采用的不同方法,但作为一个 tl;dr,在配置更改期间没有简单/简单的方法来保持 Activity 范围内的东西。
  • 感谢大卫的回复。我目前正在尝试使用加载器保存演示者的状态,我不确定结果:)。我不确定如何在配置更改时保留相同的 MainActivityComponent 实例,因为我必须在 MainActivity 中而不是在 Application 类中初始化 MainActivityComponent,因为我需要模块中的 MainActivity 实例。你能否给我推荐一些博客或一些很好的解释,这将在我的 Dagger 体验中给我一些支持。谢谢

标签: android dagger-2 android-mvp dagger


【解决方案1】:

您必须决定是否要在屏幕旋转时销毁并重新创建 Activity(即“配置更改”)。如果您想自己处理,我建议您只需在 AndroidManifest.xml 中进行更改;如果你想通过 Dagger 来处理它,你需要将你的数据保存在一个寿命更长的对象中(比如你的 ApplicationComponent)。

the official docs on "Handling Configuration Changes" 一样,您可以指示您的 Activity 简单地处理方法调用而不是重新启动:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

现在,当这些配置之一发生更改时,MyActivity 不会重新启动。相反,MyActivity 会收到对onConfigurationChanged() 的调用。该方法传递了一个Configuration 对象,该对象指定了新的设备配置。通过阅读Configuration 中的字段,您可以确定新配置并通过更新界面中使用的资源进行适当的更改。

重要的是,这可以让您的 ActivityComponent 与您的 Activity 本身一样长寿,并且可以更好地推断您的 Activity 实例何时有效或陈旧。您仍然需要为 Android 的多任务处理加载和保存数据,但无论您如何使用 Dagger,这都是事实。

如果您认为在配置更改时销毁和重新创建 Activity 很重要,那很好,但如果您要创建或修改组件以使其寿命长于单个 Activity 实例。这将是该术语的非典型用法,并且可能会让其他开发人员感到非常困惑。相反,如果您希望 Dagger 组件为多个 Activity 实例(多个 Activity 类或同一 Activity 的多个实例)创建并保持状态,您应该考虑将这些对象放入现有的 ApplicationComponent 中,或者创建一个新组件(例如"SessionComponent") 的寿命比一个 ActivityComponent 长,但比你的 ApplicationComponent 短。如果你这样做,你需要非常小心,这个对象中的任何内容都不会保留 Activity 实例、视图或任何与单个 Activity 永久关联的东西:这会导致内存泄漏,因为 Android 无法在您的 SessionComponent 或 ApplicationComponent 持有对它的引用时,对 Activity 的这些部分进行垃圾收集。

【讨论】:

  • 感谢您的回复,杰夫现在说得通了。我仍然不确定如何在 Application 类中初始化 SessionComponent 并仍然为 MainActivityModule 提供 MainAcivity 实例。希望我能找到一些示例,其中模块依赖于外部依赖项,并且它是在 Application 类中创建的。谢谢
  • 亚历山大,很高兴为您提供帮助!至于如何初始化 SessionComponent,你让它对你的应用程序可用,就像你让 ApplicationComponent 可用一样,你只是不将 Application 或 Activity 传递给它。棘手的部分是,您需要找出知道何时使用同一个会话以及何时创建新会话的最佳方法; Bundle 将对此有所帮助,但这是我建议您自己处理配置更改的部分原因。干杯!
【解决方案2】:

创建一个 Application 类并将 Dagger 初始化移动到 Application 类的 onCreate() 方法。通过这样做,您的匕首初始化将贯穿您的应用程序范围。

您面临的这个问题是因为如果方向改变,您的 Activity 会被销毁,并且会创建新的 Activity。所以在 Activity 的 onCreate 方法中初始化 dagger 并不是正确的做法。

并确保在你的 dagger @provides 方法中添加 @singleton。

public class MainApplication extends Application {
@Override
public void onCreate() {
    super.onCreate();
    mainApplication = this;
    component = DaggerMainActivityComponent.builder()
            .mainActivityModule(new MainActivityModule(this))
            .applicationComponent(TrainningDagger3.get(this).getComponent())
            .build();
}

并且不要忘记在清单的应用程序标签中添加 android:name=".MainApplication"

【讨论】:

  • 感谢您的帮助。我有两个组件,一个是ApplicationComponent,另一个是MainActivityComponent。 MainActivityComponent 依赖于 ApplicationComponent。我在应用程序类中初始化 ApplicationComponent,在 MainActivity 中初始化 MainActivityComponent。您认为这是在 Application 类中初始化两个组件的好方法吗?谢谢!
  • 在每个活动中使用活动明智的组件不是一个好方法。您可以将所有活动作为一个组使用一个活动组件。看看这个link 和这个link 和这个link。 :)
  • @Harish,我完全不同意:将 Activity 组件与 Application 组件分开的全部原因是拥有反映 Activity 生命周期的对象。此外,由于类加载组件的开销,理想的(如果 APK-size-heavy)为每个 Activity 创建一个单独的 ActivityComponent,这样您就不需要为 每个 i> Activity 以便创建一个 Activity。请参阅dagger.android,了解官方的每个活动一个组件的框架。
  • (您还可以从指向dagger.android 的链接中看到,在 Activity 的 onCreate 中初始化 dagger 是完全正确的方法。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多