Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2 and Retrofit 2 change base URL

In my case, I need to change URL dynamically, but I don't want to create 2 instances of the retrofit client. I'm trying to change base URL via interceptor modifications, but retrofit still uses the old value. What am I doing wrong?

App.java

public class App extends Application {
    private static AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        appComponent =
                DaggerAppComponent
                        .builder()
                        .appModule(new AppModule(this))
                        .build();

    }

    @NonNull
    public static App get(@NonNull Context context) {
        return (App) context.getApplicationContext();
    }

    public static AppComponent getAppComponent() {
        return appComponent;
    }
}

AppModule.java

@Module
public class AppModule {
    private Context context;

    public AppModule(Context context) {
        this.context = context;
    }

    @Provides
    @Singleton
    Context provideContext() {
        return context;
    }
    
}

NetModule.java

@Module
public class NetModule {

    @Provides
    @Singleton
    Gson provideGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
        return gsonBuilder.create();
    }
    @Provides
    @Singleton
    MainInterceptor provideMyApiInterceptor() {
        return MainInterceptor.get();
    }

    @Provides
    @Singleton
    OkHttpClient provideOkhttpClient() {
        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.readTimeout(15, TimeUnit.SECONDS);
        client.connectTimeout(20, TimeUnit.SECONDS);
        return client.build();
    }

    @Provides
    @Singleton
    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
        return new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl("first.url.com")
                .client(okHttpClient)
                .build();
    }
}

NetComponent.java

@Singleton
@Component(modules = NetModule.class)
public interface NetComponent {
    Retrofit getRetrofit();

    MainInterceptor getInterceptor();
}

MainInterceptor.class

public class MainInterceptor implements Interceptor {
    private static MainInterceptor sInterceptor;
    private String mScheme;
    private String mHost;

    public static MainInterceptor get() {
        if (sInterceptor == null) {
            sInterceptor = new MainInterceptor();
        }
        return sInterceptor;
    }
    
    private MainInterceptor() {
    }

    public void setInterceptor(String url) {
        HttpUrl httpUrl = HttpUrl.parse(url);
        mScheme = httpUrl.scheme();
        mHost = httpUrl.host();
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();

        if (mScheme != null && mHost != null) {
            HttpUrl newUrl = original.url().newBuilder()
                    .scheme(mScheme)
                    .host(mHost)
                    .build();
            original = original.newBuilder()
                    .url(newUrl)
                    .build();
        }
        return chain.proceed(original);
    }
}

And this is the code to initialize the component in some class.

NetComponent component= DaggerNetComponent.create();
DataService service = component.getRetrofit().create(DataService.class);
MainInterceptor interceptor = component.getInterceptor();
interceptor.setInterceptor("second.url.com");
service.getSomeData();

After that, the URL is still "first.url.com"

like image 742
Mikhail Avatar asked Jul 26 '17 17:07

Mikhail


People also ask

How do you dynamically change base URL in retrofit?

For latest Retrofit library, you can simply use singleton instance and change it with retrofitInstance. newBuilder(). baseUrl(newUrl) . No need to create another instance.

Can you use multiple baseUrl in retrofit?

Yes, you can create two different Service instances.


1 Answers

The simple way is to use @Named:

@Provides
@Singleton
@Named("retrofit_1")
Retrofit provideRetrofit1(Gson gson, OkHttpClient okHttpClient) {
        return new Retrofit.Builder()
                ...
                .baseUrl("url_1.com")
                ...;}

@Provides
@Singleton
@Named("retrofit_2")
Retrofit provideRetrofit2(Gson gson, OkHttpClient okHttpClient) {
        return new Retrofit.Builder()
                ...
                .baseUrl("url_2.com")
                ...;}

then use the same @Named:

@Provides
IApi1 provideApi_1(@Named("retrofit_1") RestAdapter adapter){....}

@Provides
IApi2 provideApi_2(@Named("retrofit_2") RestAdapter adapter){....}
like image 98
Siarhei Avatar answered Oct 19 '22 23:10

Siarhei