Dagger 2:是否建议为Activities和fragments使用静态provider?

3

我最近观看了Gregory Kick关于Dagger 2的演讲(链接)。他在那里解释了静态提供程序方法,这可以帮助提高性能。因此,我正在修改项目中的所有提供程序方法为static。但是我有一个疑问。在我的项目中,有一些提供程序返回活动实例(外部依赖项)。因此,我编写了一个带有构造函数的module,该构造函数从外部获取Activity

@Module
public class ActivityModule {
  private static BaseActivity mActivity;

  public ActivityModule(BaseActivity activity) {
    mActivity = activity;
  }

  @ActivityScope
  @Provides
  Activity mActivity() {
    return mActivity;
  }

  @ActivityScope
  @Provides
  BaseActivity baseActivity() {
    return mActivity;
  }
}

如果我必须将提供程序设置为静态的话,它会像下面这样:

@Module
public class ActivityModule {
  private static BaseActivity mActivity;

  public ActivityModule(BaseActivity activity) {
    mActivity = activity;
  }

  @ActivityScoped
  @Provides
  static Activity mActivity() {
    return mActivity;
  }

  @ActivityScoped
  @Provides
  static BaseActivity baseActivity() {
    return mActivity;
  }
}

所以,我将活动实例保存在一个静态成员中。这会导致任何内存泄漏吗?或者dagger会自动管理它,当活动被销毁时删除静态引用? 在这种情况下保留静态提供程序是推荐的吗?

2
内存泄漏满天飞 - EpicPandaForce
@EpicPandaForce 所以,只有在这种情况下,我应该避免使用静态提供程序吗? - user4260260
除非你在 onDestroy() 中将该字段重置为 null,否则是的。 - EpicPandaForce
从静态提供程序返回一个新的片段实例怎么样? - user4260260
@Provides @ActivityScoped static MyFragment provideFragment() { return MyFragment.createInstance(); } - user4260260
显示剩余2条评论
1个回答

6

是否建议对活动和片段使用静态提供程序?

不建议。 这样做只会创建错误和内存泄漏的来源。一般来说,永远不要将任何Android框架类型放入静态变量中。它们引用了context,会导致内存泄漏。

如上所述,静态方法可能会提供性能提升,当然您可以使用它。您所示代码的问题是返回静态变量的静态方法,这也有点扰乱了调用模块构造函数的目的。

如果您有一个仅由静态方法组成的模块,您可能会获得额外的性能,并消除模块实例分配的需要,正如链接的演讲中所提到的。

静态方法本身是可以的,但它们不应与您应用程序的其他部分交互,例如读取或写入静态变量。如果您依赖于其他对象,请始终将它们作为参数添加到提供方法中。这样Dagger就可以正确使用这些方法,您也可能获得一些性能提升。

What about returning a new fragment instance from a static provider?

@Provides @ActivityScoped static MyFragment provideFragment() {
  return MyFragment.createInstance();
}
我相信这应该没问题。它是一个静态方法,返回一个新的 Fragment 实例,并且不应包含任何副作用。
请确保每当 Activity 重新创建时重新创建您的 @ActivityScoped 组件,并且 Fragment 不会保留其状态。您真的要避免 FragmentManager 管理与组件中的 Fragment 不同的 Fragment,更糟糕的是两者都管理。

2
据我所知,只要您对“@ActivityScoped”片段与您的Activity一样长久感到舒适,那么这是彻底和正确的。如果您的Activity寿命很长且Fragment很重,则可能不希望将Fragment设置为“@ActivityScoped”,以便垃圾收集器在不再显示时清除Fragment。 - Jeff Bowman
不错的回答 +1,但我通常会告诉人们不要提供Fragments,因为如果他们使用FragmentManager,存在很大的出错风险。 - David Rawson
所以基本上,我可以使用静态提供者来为我的应用程序范围组件的所有提供者提供服务,除了Activity、Fragment、Context或类似的框架组件?对于应用程序范围组件(如Retrofit、Gson、Util类),使用静态提供者是安全的,对吗? - user4260260
1
@Jrd 你可以使用utils、gson和co的静态提供程序为所有组件提供支持。但是,作为经验法则,请勿从它们中提供Android框架部分。因此,是的,这样做是安全的。 - David Medenjak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接