在我的应用程序中,我有一个ApplicationScope,它为我提供了上下文和共享首选项之类的东西。
2个子组件,LoggedInComponent和LoggedOutComponent。
这两个子组件具有与该问题不太相关的其他子组件。

我有一个NetworkModule来创建我的改造实例。
这两个子组件都需要NetworkModule,但是由于基本URL和其他设置可能会更改,因此在登录过程中更改可能会更改。

我想知道哪种方法更好:
1.为LoggedIn和LoggedOut子组件以及NetworkModule赋予相同的作用域,以便两个子组件都可以使用此模块。感觉有点hacky和错误使用范围。
2.使用ApplicationScope将网络模块放入AppComponent中。还会错误使用范围,因为重新创建了网络模块,因此它不能具有相同的范围,并且每次重新创建都会导致重新创建AppComponent及其子组件。

你会怎么做?也许有更好的解决方案?

最佳答案

您不希望LoggedInComponent和LoggedOutComponent具有不同的网络行为,并且不一定需要在LoggedInComponent或LoggedOutComponent的整个生命周期内保持一致的网络行为,因此让它们分别绑定NetworkModule毫无意义。我认为通过AppComponent使它们可用是有意义的。请记住,并非AppComponent中的所有内容都需要具有ApplicationScope:您可以在AppComponent中进行无作用域的绑定,这将指示Dagger每次重新获取或重新创建所请求的对象。

具体来说,我将NetworkModule绑定到AppComponent的子组件中,您可以在NetworkModule配置每次更改时重新创建。这不仅使您可以封装某些网络详细信息(请参阅《 Dagger用户指南》中的"subcomponents for encapsulation"),而且,如果您正在寻找的话,还可以使您在整个网络绑定中利用依赖项注入。

为了确保获得正确的当前NetworkComponent,可以创建一个单例绑定(ApplicationScope)的NetworkManager。您可以使用它来保存最新的NetworkComponent。

@Module(subcomponents={NetworkComponent.class})
public abstract class ApplicationModule {
  /** Unscoped. Fetch this fresh from NetworkComponentHolder each time. */
  @Provides Retrofit provideRetrofit(NetworkManager manager) {
    return manager.getNetworkComponent().getRetrofit();
  }
}

@ApplicationScope public class NetworkManager {
  private final Provider<NetworkComponent.Builder> builderProvider;
  private NetworkComponent currentComponent;

  @Inject public NetworkComponentHolder(
      Provider<NetworkComponent.Builder> builderProvider) {
    this.builderProvider = builderProvider;
    currentComponent = builderProvider.get()
        .withNetworkModule(getDefault())
        .build();
  }

  public void updateSettings(String baseUrl) {
    currentComponent = builderProvider.get()
        .withNetworkModule(new NetworkModule(baseUrl))
        .build();
  }

  public NetworkComponent getNetworkComponent() {
    return currentComponent;
  }
}


有了这个,您在AppComponent,LoggedInComponent和LoggedOutComponent中的大多数代码都可以在需要发出请求时注入Retrofit(或Provider<Retrofit>)。当响应返回告诉您更新基本URL时,您可以插入NetworkManager,调用updateSettings,突然,对Retrofit的新请求将返回您的新实例。 (但是请注意,改造的旧实例可能仍然存在,但是只要您更改属于现有实例的依赖项,就会遇到该问题。)

ps。如果NetworkModule足够轻巧,或者具有足够的绑定,则您可以选择直接将NetworkModule放到ApplicationComponent上,并简单地让NetworkManager保留当前的Retrofit实例等。您必须根据所需的绑定数进行判断与要封装或隐藏在子组件中的绑定数量相比,它要像provideRetrofit那样通过。

关于android - Dagger2一个模块,用于两个不同的作用域,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43126682/

10-11 03:22