Ren*_*ith 45 android dagger-2 retrofit2
我正在尝试使用Dagger 2使用Retrofit 2.0执行登录操作
这是我如何设置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;
}
Run Code Online (Sandbox Code Playgroud)
这是API接口.
interface LoginAPI {
@GET(relative_path)
Call<Boolean> logMe();
}
Run Code Online (Sandbox Code Playgroud)
我有三个不同的基本网址用户可以登录.因此,在设置Retrofit依赖项时,我无法设置静态URL.我在Application类上创建了一个setUrl()和getUrl()方法.用户登录后,我在调用API调用之前将url设置为Application.
我像这样使用懒惰注射进行改造
Lazy<Retrofit> retrofit
Run Code Online (Sandbox Code Playgroud)
这样,只有当我可以打电话时,Dagger才会注入依赖关系
retrofit.get()
Run Code Online (Sandbox Code Playgroud)
这部分效果很好.我把url设置为改进依赖.但是,当用户键入错误的基本URL(例如,mywifi.domain.com)时,会出现问题,理解它是错误的并更改它(比如mydata.domain.com).由于Dagger已经为改造创建了依赖关系,因此它不会再做了.所以我必须重新打开应用程序并输入正确的URL.
我阅读了不同帖子,使用Dagger在Retrofit上设置动态网址.在我的情况下,没有什么比这更好的了.我想念什么吗?
Epi*_*rce 46
在Retrofit2中删除了对此用例的支持.建议使用OkHttp拦截器.
HostSelectionInterceptor 由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());
}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以替换您的Retrofit实例(并且可能将实例存储RetrofitHolder在您可以修改实例本身的实例中,并通过Dagger提供持有者)...
public class RetrofitHolder {
Retrofit retrofit;
//getter, setter
}
Run Code Online (Sandbox Code Playgroud)
或者重新使用当前的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);
Run Code Online (Sandbox Code Playgroud)
小智 43
Retrofit2库附带一个@Url注释.您可以baseUrl像这样覆盖:
API接口:
public interface UserService {
@GET
public Call<ResponseBody> profilePicture(@Url String url);
}
Run Code Online (Sandbox Code Playgroud)
并调用这样的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");
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅以下链接:https://futurestud.io/tutorials/retrofit-2-how-to-use-dynamic-urls-for-requests
这在 Kotlin 中对我有用
class HostSelectionInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val host: String = SharedPreferencesManager.getServeIpAddress()
val newUrl = request.url().newBuilder()
.host(host)
.build()
request = request.newBuilder()
.url(newUrl)
.build()
return chain.proceed(request)
}
}
Run Code Online (Sandbox Code Playgroud)
将拦截器添加到 OkHttpClient 构建器
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HostSelectionInterceptor())
.cache(null)
.build()
Run Code Online (Sandbox Code Playgroud)
小智 6
感谢@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);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
这可能会晚,但Retrofit允许您在使用@Url注释进行网络调用时使用动态 URL 。我还使用在我的存储库中Dagger2注入Retrofit实例,这个解决方案对我来说很好用。
由您在创建 Retrofit 实例时提供。
@GET("/product/123")
fun fetchDataFromNetwork(): Call<Product>
Run Code Online (Sandbox Code Playgroud)
并使用您将在运行时提供此调用的 url。
@GET()
fun fetchDataFromNetwork(@Url url : String): Call<Product> //
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28649 次 |
| 最近记录: |