Retrofit 2.0とDagger 2を使用した動的なベースURLの設定
質問
Retrofit 2.0を使ってDagger 2でログインアクションを行おうとしています。
Retrofitの依存関係を設定する方法は以下の通りです。
@Provides
@Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient client) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson)
.client(client)
.baseUrl(application.getUrl())
.build();
return retrofit;
}
これがAPIのインターフェイスです。
interface LoginAPI {
@GET(relative_path)
Call<Boolean> logMe();
}
私はユーザーがログインできる3つの異なるベースURLを持っています。そのため、Retrofitの依存関係を設定する際に、固定URLを設定することができません。そこで、ApplicationクラスにsetUrl()とgetUrl()メソッドを作成しました。ユーザーがログインしたときに、APIコールを呼び出す前にアプリケーションにURLを設定するようにしました。
Retrofitのレイジーインジェクションはこんな感じで使っています。
Lazy<Retrofit> retrofit
を呼び出せるときだけ、Daggerは依存性を注入します。
retrofit.get()
この部分はうまくいきました。私は、urlを後付けの依存性に設定しました。しかし、ユーザーが間違ったベースURL(例えばmywifi.domain.com)を入力し、それが間違ったものだと理解して変更(例えばmydata.domain.comに)すると問題が発生します。Daggerはすでに後付けの依存関係を作成しているため、再度変更することはできません。 そのため、アプリを再度開き、正しいURLを入力する必要があります。
Daggerを使ってRetrofitに動的URLを設定するためのさまざまな投稿を読みました。私の場合、うまくいったものがありません。何か見落としているのでしょうか?
どのように解決するのですか?
このユースケースのサポートは Retrofit2 で削除されました。代わりに OkHttp インターセプターを使うことが推奨されています。
HostSelectionInterceptor
作成者
スワンクジェス
import java.io.IOException;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
/** An interceptor that allows runtime changes to the URL hostname. */
public final class HostSelectionInterceptor implements Interceptor {
private volatile String host;
public void setHost(String host) {
this.host = host;
}
@Override public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String host = this.host;
if (host != null) {
//HttpUrl newUrl = request.url().newBuilder()
// .host(host)
// .build();
HttpUrl newUrl = HttpUrl.parse(host);
request = request.newBuilder()
.url(newUrl)
.build();
}
return chain.proceed(request);
}
public static void main(String[] args) throws Exception {
HostSelectionInterceptor interceptor = new HostSelectionInterceptor();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Request request = new Request.Builder()
.url("http://www.coca-cola.com/robots.txt")
.build();
okhttp3.Call call1 = okHttpClient.newCall(request);
okhttp3.Response response1 = call1.execute();
System.out.println("RESPONSE FROM: " + response1.request().url());
System.out.println(response1.body().string());
interceptor.setHost("www.pepsi.com");
okhttp3.Call call2 = okHttpClient.newCall(request);
okhttp3.Response response2 = call2.execute();
System.out.println("RESPONSE FROM: " + response2.request().url());
System.out.println(response2.body().string());
}
}
あるいは、Retrofit のインスタンスを置き換える (そしておそらくそのインスタンスを
RetrofitHolder
に格納し、インスタンス自体を変更し、Daggerを通してホルダーを提供することができます)...
public class RetrofitHolder {
Retrofit retrofit;
//getter, setter
}
あるいは、現在のRetrofitのインスタンスを再利用して、新しいURLをリフレクションでハックすることもできます。Retrofitは
baseUrl
というパラメータがあります。
private final
であるため、リフレクションでのみアクセスすることができます。
Field field = Retrofit.class.getDeclaredField("baseUrl");
field.setAccessible(true);
okhttp3.HttpUrl newHttpUrl = HttpUrl.parse(newUrl);
field.set(retrofit, newHttpUrl);
関連
-
[解決済み】Retrofit 2 - ダイナミックURL
-
[解決済み] SDカードからファイルを削除する方法を教えてください。
-
[解決済み] android: imageview の画像を画面に合わせて伸縮させる
-
[解決済み] AndroidにおけるViewPager2の適切な実装
-
[解決済み] Eclipseでのandroid:configChangesでのAdmobエラー
-
[解決済み] Androidのソースコードにある@hideの意味とは?
-
[解決済み] Android ConstraintLayout - あるビューを別のビューの上に配置する
-
[解決済み] 文字サイズとアンドロイドの画面サイズの違い
-
[解決済み] アンドロイドでシェイクを検出するには?
-
[解決済み] 非推奨のandroid.support.v4.app.ActionBarDrawerToggleの置き換え方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] アンドロイドフラグメント onRestoreInstanceState
-
[解決済み] プログラム的に電話をかけるには?
-
[解決済み] 「KotlinとAndroidで「パラメータTを推測するのに十分な情報がありません。
-
[解決済み] DialogFragmentを正しく終了させるには?
-
[解決済み] Androidのadb logcatでTAG名で特定のメッセージを除外する方法は?
-
[解決済み] Android端末がHDPI画面かMDPI画面かを確認する方法は?
-
[解決済み] edittextのテキストがメールアドレスかどうかを確認するには?
-
[解決済み] アンドロイドボタンセレクター
-
[解決済み] Recyclerviewと異なるタイプの行のインフレーションの処理
-
[解決済み] HttpURLConnectionを使ったPOSTによるファイル送信