将依赖项注入未分区对象 - 最佳实践?

时间:2016-03-10 21:42:50

标签: android dependency-injection parcelable dagger-2

我有一个域实体 - 我们假设它是Car - 它包含我通过Dagger注入的存储库实现。当我测试我的实体时,我将存储库替换为模拟实现。 Carimplements Parcelable

Dagger可以在调用Car(Engine)时构造对象,但是当调用Car(Parcel)时它显然无法执行,因为它是由Parcelization Framework在内部调用的(通常是从Car获取IntentCar(Parcel))。

Parcel构造函数中手动注入依赖项是一个好主意吗?或者,您可以推荐最佳做法吗?在public class Car implements Parcelable { @Inject ICarRepository CarRepositoryImpl; private Engine engine; // User specified engine passed through constructor public Car(Engine engine) { this.engine = engine; } public Car(Parcel parcel) { this.engine = getEngine(parcel); // Read engine from parcel // Inject dependencies here? } // Static Parcelable creator and other methods follow... } 构造函数中注入依赖项肯定会解决我的问题,但建议不要在构造函数中注入依赖项,以便在实例化和注入逻辑之间保持关注点分离。

这是我的域名实体

{{1}}

2 个答案:

答案 0 :(得分:3)

David对您的问题发表了评论 - 为什么Car会依赖CarRepository?这绝对是一种反模式 - 存储库用于将实体与建模/持久性分离;在这里你介绍一个看似没有任何理由。但是,让我们假设您只是为了举例而将存储库放在那里。

当然,Dagger没有自动的方法来准备一个被取消的对象。这意味着,我们必须在某个地方调用Dagger。

根据我的判断,合适的候选人将是您的public static final Parcelable.Creator CREATOR,如下:

// Creator
public static final Parcelable.Creator<Car> CREATOR 
    = new Parcelable.Creator<>() {
        public Car createFromParcel(Parcel in) {
            Car ret = new Car(in);
            DaggerCarComponent.builder().build().inject(ret);
            return ret;
        }
};

使用此技术取得的目标

  • 您的Dagger特定代码不会与构造函数中的实例化逻辑纠缠在一起,而是作为un-parcelling的特定实现。
  • 您的Dagger特定代码是静态的,可以单独测试,而无需通过Car实例化Parcel
  • 使用@Component,您的代码不仅可以抵御未来的更改(例如添加或删除依赖项),还可以使用极简主义/ DRY

答案 1 :(得分:0)

一种可能的解决方案是所谓的“可拆分注入模式”: https://medium.com/@felix.kirchengast/mocking-intents-the-parcelable-injection-pattern-88be4abcccb3

这意味着要覆盖静态CREATOR对象,类似于静态依赖项注入。