Dagger 2を使用してRetrofit 2.0を使用してログインアクションを実行しようとしています
レトロフィットの依存関係を設定する方法は次のとおりです
@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をApplicationに設定します。
私はこのような改造のために怠laな注入を使用します
Lazy<Retrofit> retrofit
そうすれば、Daggerは、呼び出し可能な場合にのみ依存関係を注入します
retrofit.get()
この部分はうまく機能します。 URLをレトロフィット依存に設定しました。ただし、ユーザーが間違ったベースURL(mywifi.domain.comなど)を入力し、それが間違っていることを理解して変更すると(mydata.domain.comなどに)問題が発生します。 Daggerは既に改造のための依存関係を作成しているため、再度行うことはありません。そのため、アプリを再度開き、正しいURLを入力する必要があります。
Daggerを使用してRetrofitで動的URLを設定するためのさまざまな投稿を読みました。私の場合、何もうまくいきませんでした。私は何かを見逃していますか?
この使用例のサポートはRetrofit2で削除されました。代わりにOkHttpインターセプターを使用することをお勧めします。
HostSelectionInterceptor
made(swankjesse
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をリフレクションでハッキングします。これは、ルールを台無しにしているためです。レトロフィットにはbaseUrl
パラメーターがあり、これはprivate final
、したがって、リフレクションでのみアクセスできます。
Field field = Retrofit.class.getDeclaredField("baseUrl");
field.setAccessible(true);
okhttp3.HttpUrl newHttpUrl = HttpUrl.parse(newUrl);
field.set(retrofit, newHttpUrl);
Retrofit2ライブラリには@Url
注釈。次のようにbaseUrl
をオーバーライドできます。
APIインターフェース:
public interface UserService {
@GET
public Call<ResponseBody> profilePicture(@Url String url);
}
そして次のようにAPIを呼び出します:
Retrofit retrofit = Retrofit.Builder()
.baseUrl("https://your.api.url/");
.build();
UserService service = retrofit.create(UserService.class);
service.profilePicture("https://s3.Amazon.com/profile-picture/path");
詳細については、次のリンクを参照してください。 https://futurestud.io/tutorials/retrofit-2-how-to-use-dynamic-urls-for-requests
助けてくれた@EpicPandaForceに感謝します。誰かがIllegalArgumentExceptionに直面している場合、これは私の作業コードです。
public class HostSelectionInterceptor implements Interceptor {
private volatile String Host;
public void setHost(String Host) {
this.Host = HttpUrl.parse(Host).Host();
}
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String reqUrl = request.url().Host();
String Host = this.Host;
if (Host != null) {
HttpUrl newUrl = request.url().newBuilder()
.Host(host)
.build();
request = request.newBuilder()
.url(newUrl)
.build();
}
return chain.proceed(request);
}
}
スコープのない提供メソッドを使用して、新しいオブジェクトをインスタンス化できます。
@Provides
LoginAPI provideAPI(Gson gson, OkHttpClient client, BaseUrlHolder baseUrlHolder) {
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)
.client(client)
.baseUrl(baseUrlHolder.get())
.build();
return retrofit.create(LoginAPI.class);
}
@AppScope
@Provides
BaseUrlHolder provideBaseUrlHolder() {
return new BaseUrlHolder("https://www.default.com")
}
public class BaseUrlHolder {
public String baseUrl;
public BaseUrlHolder(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
}
これで、コンポーネントからbaseUrlHolderを取得してベースURLを変更できます
App.appComponent.getBaseUrlHolder().set("https://www.changed.com");
this.loginApi = App.appComponent.getLoginApi();