1

我有三个数据源:

  • 一个 JSON API
  • Github
  • XML 清单

我正在使用 Retrofit 和 OkHttp 等来访问所有这些:

  • JSON API 使用 Gson 反序列化
  • XML Manifest 返回一个字符串,我将对其进行反序列化
  • Github 返回一个我显示的字符串

JSON 和 XML 将使用相同的实体进行反序列化。因此,我想将我的 MVP 代码编写得足够抽象,以至于它只需要实体。

所以,我为此写了一个接口

public interface BaseRomRepository {
    // Addons
    Call<List<AddonEntity>> getAddons(String slug);
    Call<List<AddonEntity>> getAddons(int id);

    Call<AddonEntity> getAddon(String slug);
    Call<AddonEntity> getAddon(int id);

    // Versions
    Call<List<VersionEntity>> getVersions(String slug);
    Call<List<VersionEntity>> getVersions(int id);

    Call<VersionEntity> getVersion(String slug);
    Call<VersionEntity> getVersion(int id);
}

所以,我的 Presenters 和 Interactors 可以简单地调用这些方法,它应该取决于实际使用 Repository 的实现。

然而,这就是我卡住的地方。我不确定使用 Dagger 2 执行此操作的最佳方法。我确信它适用于此用例,但我正在努力弄清楚在哪里/如何执行此操作。

我说得对吗?存储库和反序列化轻松地存在于 MVP 模型中。所有这些都应该发生在那里,Presenter 层可能相对不知道正在使用哪个存储库?

我会展示更多代码,但它非常混乱,我现在很难抽象成一种更易读的方式。

编辑:

这是一个 Gist,其中包含我到目前为止的一些实现:https ://gist.github.com/MatthewBooth/e3dd7a1f3a19fa0fd18e811752170be6

4

2 回答 2

1

如果你想为同一个接口提供不同的实现,你可以创建一个@Module类,并使用@Named注解。

在您的模块中:

@Provides
@Named("xmlRepository")
BaseRomRepository provideXmlRepository() {
    return new XmlRepository();
}

@Provides
@Named("restRepository")
BaseRomRepository provideRestRepository() {
    return new RestRepository();
}

@Provides
@Named("githubRepository")
BaseRomRepository provideGithubRepository() {
    return new GithubRepository();
}

这样在代码中你可以简单地使用:

@Inject
@Named("xmlRepository")
BaseDomRepository xmlRepo;
@Inject
@Named("githubRepository")
BaseDomRepository githubRepo;
@Inject
@Named("restRepository")
BaseDomRepository restRepo;

或者在你的模块中

@Provides
@Singleton
AddonInteractor providesAddonInteractor(@Named("xmlRepository") BaseRomRepository repository) {
    return new AddonInteractorImpl<>(repository);
}

编辑:我会保留上面的内容,因为我认为它对其他人有用。

当我们在评论中进一步深入研究时,似乎 OP 想要一种不同的方法。

您不需要 @Named 注释。此类情况使用应用程序变体处理。您创建了 3 种应用风格:rest、xml、github。您将所有代码保存在main. 然后你放了 3 个实现,比方说RepositoryModule,每一个都实例化你的BaseDomRepository.

看到这个:https ://developer.android.com/studio/build/build-variants.html

于 2017-05-01T16:34:29.593 回答
0

考虑在 dagger2 中使用命名和单例注释。

@Module
public class BasicModule {

    @Provides
    @Named("basic")
    @Singleton
    public BasicServer provideBasicServer() {
        return new BasicServer();
    }

    @Provides
    @Named("basic")
    @Singleton
    public BasicServer provideBasicServer() {
        return new BasicServer();
    }
}

如果我们需要两个具有相同返回类型的不同对象,我们可以使用 @Named 限定符注解。您将在提供单例的位置(@Provides 注释)和注入它们的位置(@Inject 注释)定义它:

于 2017-05-01T16:41:57.893 回答