Dagger + Retrofit dynamic URL

前端 未结 2 484
遇见更好的自我
遇见更好的自我 2020-12-01 15:27

PROBLEM

I need to call API from domains entered by USER and I need to edit my Retrofit singleton before the call accordingly to the ins

相关标签:
2条回答
  • 2020-12-01 15:36

    You can implement BaseUrl and pass that instead of a fixed URL.check out this link Other approach is implementing Endpoint and make use of setUrl().So for changing some header value at run time then you can use interceptor and add it to OkHttp.

    0 讨论(0)
  • 2020-12-01 15:46

    I see 2 options here:

    • Use dagger as it is intended. Create for every baseUrl their own Retrofit client, or
    • Use an interceptor to modify the request before sending it

    Dagger approach

    If you were to brute force urls, this would probably not be the right choice, since it relies on creating a new Retrofit instance for each.

    Now every time the url changes, you just recreate the following demonstrated UrlComponent by supplying it with a new UrlModule.

    Clean up

    Clean your @Singleton module, so that it provides GsonConverterFactory, and RxJavaCallAdapterFactory to make proper use of dagger and not recreate shared objects.

    @Module
    public class SingletonModule {
    
      @Provides
      @Singleton
      GsonConverterFactory provideOkHttpClient() {/**/}
    
      @Provides
      @Singleton
      RxJavaCallAdapterFactory provideOkHttpClient() {/**/}
    }
    
    
    @Singleton
    @Component(modules = SingletonModule.class)
    interface SingletonComponent {
    
        // sub component
        UrlComponent plus(UrlModule component);
    }
    

    Url Scoped

    Introduce a @UrlScope to scope your Retrofit instances.

    @Scope
    @Retention(RetentionPolicy.RUNTIME)
    public @interface UrlScope {
    }
    

    Then create a subcomponent

    @SubComponent(modules=UrlModule.class)
    public interface UrlComponent {}
    

    And a module for it

    @Module
    class UrlModule {
    
        private final String mUrl;
    
        UrlModule(String url) { mUrl = url; }
    
        @Provides
        String provideUrl() {
            return mUrl;
        }
    
        @Provides
        @UrlScope
        OkHttpClient provideOkHttpClient(String url) {
            return new OkHttpClient.Builder().build();
        }
    
        @Provides
        @UrlScope
        Retrofit provideRetrofit(OkHttpClient client) {
            return new Retrofit.Builder().build();
        }
    
    }
    

    Use scoped Retrofit

    Instantiate the component and use it.

    class Dagger {
    
        public void demo() {
            UrlModule module = new UrlModule(/*some url*/);
            SingletonComponent singletonComponent = DaggerSingletonComponent.create();
            UrlComponent urlComponent = singletonComponent.plus(module);
    
            urlComponent.getRetrofit(); // done.
        }
    }
    

    OkHttp approach

    Provide a properly scoped interceptor (@Singleton in this case) and implement the corresponding logic.

    @Module
    class SingletonModule {
    
        @Provides
        @Singleton
        GsonConverterFactory provideGsonConverter() { /**/ }
    
        @Provides
        @Singleton
        RxJavaCallAdapterFactory provideRxJavaCallAdapter() { /**/ }
    
        @Provides
        @Singleton
        MyApiInterceptor provideMyApiInterceptor() { /**/ }
    
        @Provides
        @Singleton
        OkHttpClient provideOkHttpClient(MyApiInterceptor interceptor) {
            return new OkHttpClient.Builder().build();
        }
    
        @Provides
        @Singleton
        Retrofit provideRetrofit(OkHttpClient client) {
            return new Retrofit.Builder().build();
        }
    }
    
    @Singleton
    @Component(modules = SingletonModule.class)
    interface SingletonComponent {
    
        Retrofit getRetrofit();
    
        MyApiInterceptor getInterceptor();
    }
    

    todo Implement the MyApiInterceptor. You will need to have a setter for the base url, and then just rewrite / modify the requests coming through.

    Then, again, just go ahead and use it.

    class Dagger {
    
        public void demo() {
            SingletonComponent singletonComponent = DaggerSingletonComponent.create();
            MyService service = singletonComponent.getRetrofit().create(MyService.class);
            MyApiInterceptor interceptor = singletonComponent.getInterceptor();
    
            interceptor.setBaseUrl(myUrlA);
            service.doA();
            interceptor.setBaseUrl(someOtherUrl);
            service.doB();
        }
    }
    

    As a third approach, you could also use reflection to just directly change base the base URL—I added this last just for completeness.

    0 讨论(0)
提交回复
热议问题