当前位置: 首页 > 知识库问答 >
问题:

在Dagger中,子图中的单例被缓存,还是在构建新的活动子图时总是被重新创建?

程枫
2023-03-14

我使用Dagger创建活动特定对象图。在这个子图中,我使用了一个SingletonMyPresentationModel

当我退出活动并再次进入活动时,我的期望是创建活动特定对象图的新实例,这反过来会创建SingletonMyPresentationModel的新实例(凭借每个匕首的@Singleton语义。有关详细信息,请参见此答案),该实例将持续到活动特定对象图的生命周期。

然而,这不是我观察到的,每次创建特定于活动的对象图时,都会使用相同的MyPresentationModel实例。我在MyPresentationModel的构造函数中添加了一个调试点。我们第一次进入构造函数时。随后,即使在活动退出和重新进入时,我们也不会进入构造函数(正因为如此,在我的表示模型中使用的UserSession使用了第一次构造函数注入的旧值)。

虽然我可以通过使用外部公共setter在MyPresentationModel内重新设置UserSession从技术上解决这个问题,但我想更好地理解特定于活动的对象图创建/销毁的机制。

通过在我的onDestroy中取消图,这是否仍然意味着我的子图中的单件有可能在以后被重用?(可能直到他们真正GCed?)

下面是一些代码:

 // MyAppModule
 @Module(
    includes = { UserSession.class},
    injects = { MyApplication.class })
public class MyAppModule {

  private final MyApplication _app;

  MyAppModule(MyApplication app) {
    _app = app;
  }
  // ...
}


  // Main Activity

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    _activityObjectGraph = MyApplication.get()
        .getObjectGraph()
        .plus(Arrays.<Object>asList(new SubModule()).toArray());

    // Inject ourselves so subclasses will have dependencies fulfilled when this method returns.
    _activityObjectGraph.inject(this);
  }

  @Override
  protected void onDestroy() {
    _activityObjectGraph = null;
    // this eagerly allows GC, but doesn't necessarily destroy the subgraph ?
    super.onDestroy();
  }

 // SubModule
  @Module(injects = { MyPresentationModel.class, MainActivity.class },
          addsTo = MyAppModule.class,
          library = true)
  public class SubModule {}

}

// MyPresentationModel
@Singleton
public class MyPresentationModel {

  private UserSession _session;

  @Inject
  public MyPresentationModel(UserSession session) {
    _session = session;
  }

  public void someMethodThatUsesSessionInfo() {
      // _session.getUser() ...
  }
}

@weefbellington发布了一个信息丰富的答案,但读了之后我意识到我的问题不够具体和清晰。下面是尝试2:

MyAppModule(主图形)-

MySubModule(子图加在MyAppModule上)-

现在我关闭活动,销毁MySubModule(也希望是单例的MyPresentationModel),用一些新信息更新UserSession。

我再次打开MainActivity,从而从MySubModule重新创建子图,inturn提供了一个MyPresentationModel

我注意到的问题是,MyPresentationModel(本地单例)没有被再次重构,即这部分代码:

  @Inject
  public MyPresentationModel(UserSession session) {
    _session = session;
  }

只被召唤过一次。我的期望是这部分代码将再次运行,并且将再次从主图中提取User会话,并且由于它被更新,它将保存更新的值。我的问题是:子图中的单例是否缓存在其中,还是在生成新的活动子图时总是重新创建?

共有1个答案

伏默
2023-03-14

如何注入MyPresentationMoules取决于如何指定模块。例如,假设您正在注入类Foo

public class Foo {
    private final MyPresentationModel model;
    @Inject
    public Foo(MyPresentationModel model) {
        this.model = model;
    }
}

如果你的模块结构像(A),那么MyPresentationModel单例将通过主对象图注入到Foo中:

例A

@Module(injects = { Foo.class })
public class MainModule { ... }

@Module(addsTo = MainModule.class, injects = { MyPresentationModel.class })
public class SubModule { ...}

或者,如果模块的结构类似于(B),则子图将MyPresentationModelsingleton注入Foo

例B

@Module
public class MainModule { ... }

@Module(addsTo = MainModule.class, injects = { Foo.class, MyPresentationModel.class })
public class SubModule { ... }

在您的特定情况下,由于您已经指定了MyAppMoules注入MyApplication,我猜您正试图将MyPresentationModel注入到您的Application类中。这很可能不是你想做的。您可能希望使用子模块将其注入到活动类中,如(C)中所示。

例C

@Module(injects = { MainActivity.class, MyPresentationModel.class },
    addsTo = MyAppModule.class,
    library = true)
public class SubModule { ... }

public class MainActivity {
    @Inject MyPresentationModel presentationModel;
    ...
}

如果您这样做,MyPresentationModel单例将绑定到活动子图而不是主图,并且应该在活动被销毁时进行处理。

一旦掌握了Dagger的控制柄,您可能会想查看Mortary,它为您提供了对ObjectGraph子作用域的创建和销毁的更细粒度控制。

 类似资料:
  • 在循环函数中,例如的,如果我以这种方式创建对象: 在每一帧调用时,是否会重新创建此对象,或者是否会缓存它,直到它所依赖的内容(例如屏幕大小)发生更改?

  • 我目前在活动A中。我收到通知,我想在单击通知时重新创建活动A(完成A,然后再次创建)。意向类似乎没有类似于Pending帐篷的标志。标记取消当前。

  • 问题内容: 我知道“可变”和“不可变”是应该用来描述对象改变诸如Java和Objective C之类的面向对象语言中的值的能力的术语。但是,我想提出它,因为它与我的语言有关有关原始数据的问题。我知道,当我更改持有不可变对象的变量的值时,实际上是在创建一个新对象。但是,我想知道C中的基本数据的行为是否类似于不可变对象。我的意思是,当我更改保存原始数据的变量的值时,将创建新数据并由该变量引用。还是现有

  • 我正在尝试制作具有nfc功能的应用程序。问题是,当nfc标签被发现时,挂起的意图总是会产生一个已经存在的新活动。我用的是tab主机。如何在不进行新活动的情况下制作悬挂帐篷。谢谢。

  • 所以我用FragmentStatePagerAdapter实现了一个ViewPager,我有两个片段。我用参数1和2调用了setOffscreenPageLimit(),希望片段不会被重新创建,但是第一个片段总是被重新创建,而第二个片段被创建。 第一个片段总是经过这些步骤,只要它离开视野(向右滑动到另一个片段,或者点击主页按钮,等等...) on暂停 onStop onAttach 创建 onCr