2017-07-26 2 views
0

Dans mon cas, j'ai besoin de changer l'URL de façon dynamique, mais je ne veux pas créer 2 instances de client retrofit. J'essaye de changer l'URL de base via des modifications d'intercepteur, mais le stil de retrofit utilise l'ancienne valeur. Qu'est-ce que je fais mal?Dagger 2 et Retrofit 2 changent d'adresse de base

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); 
    } 
} 

Et voici le code pour initialiser le composant dans une classe.

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

Après cela, l'URL est encore "first.url.com"

+0

Reproduction possible de [Dagger + Retrofit dynamic URL] (https://stackoverflow.com/questions/36769923/dagger-retrofit-dynamic-url) –

+0

ou celui-ci: https://stackoverflow.com/q/36498131/1837367 –

Répondre

1

Lorsque vous fournissez un Retrofit, vous avez déjà réglé baseUrl "first.url.com"

return new Retrofit.Builder() 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 
      .baseUrl("first.url.com") 
      .client(okHttpClient) //<------ It not OkHttp with your MainInterCeptor 
      .build(); 

Et amusant fait est, votre MainInterceptor qui est mise en place avec une nouvelle URL est sans rapport avec votre Retrofit, parce Retrofit a été construit avec OkHttp

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

Si vous souhaitez modifier votre BASE_URL de manière dynamique, vous pouvez le faire de plusieurs façons.

public class ApiConstant { 

    public static String BASE_URL = "yourUrl"; 

    private ApiConstant() { 
    } 
} 

Créer une @Scope pour Retrofit, car il peut être modifié

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

, utilisez-le lors de la construction Rénovation

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

Ensuite, changez BASE_URL lorsque l'init DaggerActivityComponent. (Ou créer un nouveau @Scope pour une nouvelle URL)

Lire this documentation pour plus de détails

Hope this aide!

+0

Juste une question rapide, le provideRetrofit ne serait jamais exécuté qu'une seule fois, car c'est un Singleton. Comment l'URL change-t-elle alors? (En supposant, j'ai changé, ApiConstant.BASE_URL? – Tander

+0

Merci de m'avoir remarqué.Vous pouvez changer cette chaîne ou utiliser la seconde approche –

+0

Je comprends que vous pouvez changer la chaîne. Mais l'instance de Retrofit pointe toujours vers l'ancienne URL, non? – Tander