android – 使用Dagger时分离RestAdapter.build()和.create()方法的原因是什么?

在过去的几个月里,我一直在使用Dagger / Retrofit,并且已经看到了为api实现ApiModule类的常见模式.这些ApiModules通常看起来像这样:

@Provides @Singleton Client provideClient(OkHttpClient client) {
    return new OkClient(client);
  }

  @Provides @Singleton Endpoint provideEndpoint() {
    return "release".equalsIgnoreCase(BuildConfig.BUILD_TYPE)
        ? Endpoints.newFixedEndpoint(PRODUCTION_URL, "Foo Production Url")
        : Endpoints.newFixedEndpoint(STAGING_URL, "Foo Staging Url");
  }

  @Provides @Singleton Converter provideConverter(Gson gson) {
    return new GsonConverter(gson);
  }

  @Provides @Singleton RestAdapter provideRestAdapter(Endpoint endpoint, Client client,
      Converter converter) {
    return new RestAdapter.Builder()
        .setClient(client)
        .setEndpoint(endpoint)
        .setConverter(converter)
        .setLogLevel(BuildConfig.DEBUG
            ? RestAdapter.LogLevel.FULL
            : RestAdapter.LogLevel.NONE)
        .build();
  }

  @Provides @Singleton FooApi provideFooApi(RestAdapter restAdapter) {
    return restAdapter.create(FooApi.class);
  }

但要清理这个,为什么不这样做:

@Provides @Singleton Client provideClient(OkHttpClient client) {
        return new OkClient(client);
      }

@Provides @Singleton Converter provideConverter(Gson gson) {
        return new GsonConverter(gson);
      }

@Provides @Singleton FooApi provideFooApi(Client client, Converter converter) {
    return new RestAdapter.Builder()
        .setClient(client)
        .setEndpoint("release".equalsIgnoreCase(BuildConfig.BUILD_TYPE)
            ? Endpoints.newFixedEndpoint(PRODUCTION_URL, "Foo Production Url")
            : Endpoints.newFixedEndpoint(STAGING_URL, "Foo Staging Url"))
        .setConverter(converter)
        .setLogLevel(BuildConfig.DEBUG
            ? RestAdapter.LogLevel.FULL
            : RestAdapter.LogLevel.NONE)
        .build()
        .create(FooApi.class);
  }

这样做是否有任何缺点或我违反了一些Dagger合同?我问,因为有些情况下我需要在一个项目中使用多个API …像上面的第二个例子一样设置它,使这成为可能.

解决方法:

这样做有三个原因:

>通过分裂这两者,你正在创造一个关注点的分离.如何将RestAdapter实例化并放入图形中,与将服务接口的实例放入图形的方式完全不同.在这里,您碰巧将它们放在同一个模块中,但没有理由它们不能在单独的模块中,甚至不能在不同组件的库中使用它们.
>单独的提供程序允许您覆盖覆盖模块中的一个或两个以自定义行为,而无需知道对方的使用方式或来自何处.

例如,如果要在运行集成测试时启用不同的行为,则可以提供不同的RestAdapter实例.

@Provides @Singleton RestAdapter provideTestRestAdapter() {
  return new RestAdapter.Builder()
      .setEndpoint(Endpoints.newFixedEndpoint("http://mycomputer.local/api"))
      .setLogLevel(FULL)
      .build();
}

在覆盖模块中具有此功能意味着您不必更改创建服务实例的位置.
>最后,最简单的说,也许你有多个服务接口.您不应该创建多个RestAdapter实例(除非它们用于不同的端点).

@Provides @Singleton AccountService provideAccountService(RestAdapter ra) {
  return ra.create(AccountService.class);
}

@Provides @Singleton TweetService provideTweetService(RestAdapter ra) {
  return ra.create(TweetService.class);
}

@Provides @Singleton DirectMessageService provideDirectMessageService(RestAdapter ra) {
  return ra.create(DirectMessageService.class);
}
上一篇:android – 使用Retrofit访问带密钥/ id的API


下一篇:android – Retrofit RxJava – 如果我使用了Disposable.dispose(),那么当片段恢复时不会发光