【问题标题】:Handling dagger component on orientation change在方向改变时处理匕首组件
【发布时间】:2016-12-10 12:26:43
【问题描述】:

假设已经说过here,开发人员有责任保留组件实例以实现他们自己的作用域逻辑(因为作用域方法将为给定组件返回相同的实例)。

在整个活动生命周期中保持此组件引用的干净方法是什么?

示例:您正在实施 MVP 模式,因此您的 Activity 中需要一个 Presenter。此 Presenter 可以执行网络操作来下载项目。当设备旋转时,您的 Activity 将被销毁并重新创建,但您希望保持网络运行并只取回旋转前的演示者。

为 Presenter 提供自定义 PerActivity 范围的组件范围是解决方案,因此您必须通过此轮换来保持组件实例,以便注入与第一次启动 Activity 时相同的 Presenter 实例。

我们该如何处理呢?我想到了一种组件缓存(比如 HashMap ?),它可以由应用程序类中的应用程序组件提供。

【问题讨论】:

  • 您的选项是: - 应用程序中的组件缓存; - 自定义非配置实例; - 保留片段。
  • 个人我只是在当前活动不是resumed 时通过事件总线阻止事件调度,并将演示者状态放在一个包中,然后恢复其状态在事件恢复之前。因此,我的演示者没有范围。
  • 如果这种状态,例如 OkHttp 客户端正在下载数据,如何将演示者状态保存在包中?在这种情况下,似乎需要演示者缓存。
  • 我认为简短的回答是,如果执行网络操作的逻辑需要比Activity 实例更长寿,那么它不是活动范围。你能把这个逻辑转移到更广泛的范围内吗?
  • 正如我所说,通过事件总线冻结事件调度。反正我就是这么做的。如果我真的想保留它,我可能会使用保留片段的方法。

标签: java android dependency-injection dagger-2 dagger


【解决方案1】:

你可以看到ribot/android-boilerplate展示应用的实现。他们选择的解决方案是在BaseActivity 中添加一个static Map<Long, ConfigPersistentComponent>,所有活动都从该BaseActivity 扩展而来。

public class BaseActivity extends AppCompatActivity {

    private static final AtomicLong NEXT_ID = new AtomicLong(0);
    private static final Map<Long, ConfigPersistentComponent> sComponentsMap = new HashMap<>();

    private ActivityComponent mActivityComponent;
    private long mActivityId;

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

        // Create the ActivityComponent and reuses cached ConfigPersistentComponent if this is
        // being called after a configuration change.
        mActivityId = savedInstanceState != null ?
                savedInstanceState.getLong(KEY_ACTIVITY_ID) : NEXT_ID.getAndIncrement();

        ConfigPersistentComponent configPersistentComponent;
        if (!sComponentsMap.containsKey(mActivityId)) {
            // Creating new component
            configPersistentComponent = DaggerConfigPersistentComponent.builder()
                    .applicationComponent(BoilerplateApplication.get(this).getComponent())
                    .build();
            sComponentsMap.put(mActivityId, configPersistentComponent);
        } else {
            // Reusing component
            configPersistentComponent = sComponentsMap.get(mActivityId);
        }
        mActivityComponent = configPersistentComponent.activityComponent(new ActivityModule(this));
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(KEY_ACTIVITY_ID, mActivityId);
    }

    @Override
    protected void onDestroy() {
        if (!isChangingConfigurations()) {
            // Activity is finishing, removing the component
            sComponentsMap.remove(mActivityId);
        }
        super.onDestroy();
    }

    ...

}

【讨论】:

    【解决方案2】:

    网络可以与应用上下文一起使用。 这就是我将如何设计 带有 appscope 的应用组件 现在我会在应用层创建这个 ApplicationComponent 应该将上下文作为外部依赖

    接下来是在带有 peractivityscope 的 activitymodule 上扩展的 activitycomponent ..取决于 applicationcomponet

    在我的每一个活动中,我都会通过提供 applicationcomponet 来创建 activityComponet 可以通过访问此应用程序组件。 Activity.getapplication().getapplicationcomponent()

    这里确保你提供网络方法的应用模块有 appscope 如果是这种情况,即使在应用程序上,您也应该获得相同的网络。

    寻找 GitHub 应用程序示例将在下一次编辑中发布链接。

    他也值得看看 livedata(这个问题的上下文)

    【讨论】:

      猜你喜欢
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-17
      • 1970-01-01
      • 2015-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多