OKHttp + Retrofit 这一套网络框架,几乎是Android 网络请求必备的,但是再运用retrofit 这个框架时,应该更加深入去了解相关的点。这篇文章就记录自己对其理解和一些自己遇到的坑。
baseUrl
拼接问题
Retrofit retrofit = new Retrofit.Builder()
.client(builder.build())
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
通过 baseUrl(url),来确定网络请求的公共部分url, 剩余部分通过注解的方式进行拼接。假如我的公共url为:http://www.sjh.com, 但是你清楚 baseUrl 写成
.baseUrl ("http://www.sjh.com/api") 和 .baseUrl ("http://www.sjh.com/api/") 区别吗?你清楚如何修改某个请求的baseUrl ?
现在探讨一下:
<b>Base URLs should always end in {@code /}.</b>
<p>
A trailing {@code /} ensures that endpoints values which are relative paths will correctly
append themselves to a base which has path components.
<p>
<b>Correct:</b><br>
Base URL: http://example.com/api/<br>
Endpoint: foo/bar/<br>
Result: http://example.com/api/foo/bar/
<p>
<b>Incorrect:</b><br>
Base URL: http://example.com/api<br>
Endpoint: foo/bar/<br>
Result: http://example.com/foo/bar/
<p>
This method enforces that {@code baseUrl} has a trailing {@code /}.
<p>
<b>Endpoint values which contain a leading {@code /} are absolute.</b>
<p>
Absolute values retain only the host from {@code baseUrl} and ignore any specified path
components.
<p>
Base URL: http://example.com/api/<br>
Endpoint: /foo/bar/<br>
Result: http://example.com/foo/bar/
<p>
Base URL: http://example.com/<br>
Endpoint: /foo/bar/<br>
Result: http://example.com/foo/bar/
<p>
<b>Endpoint values may be a full URL.</b>
<p>
Values which have a host replace the host of {@code baseUrl} and values also with a scheme
replace the scheme of {@code baseUrl}.
<p>
Base URL: http://example.com/<br>
Endpoint: https://github.com/square/retrofit/<br>
Result: https://github.com/square/retrofit/
<p>
Base URL: http://example.com<br>
Endpoint: //github.com/square/retrofit/<br>
Result: http://github.com/square/retrofit/ (note the scheme stays 'http')
上面是 baseUrl 方法的注释,我们可以知道:
- baseUrl 最好以 / 结束,否则会忽略 url schme 后面的相对路径,比如上面的例子中说的 api;
替换BaseUrl
假如,某个接口需要替换baseUrl ,而我们又不想写一遍 httpClient ,我们可以通过这样的方式来实现:
@GET
Call<BaseResp<List<UserDiversionResp>>> getUserDiversion(@Url String fullUrl);
不在注解后面接 url, 只要在括号里加一个 @Url , 写出url的全路径即可。
提交文件
RequestBody faceApiKey = RequestBody.create(MediaType.parse("text/plain"), key);
RequestBody faceApiSecret = RequestBody.create(MediaType.parse("text/plain"), secret);
byte[] photos photo 为二进制字节流
RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), photos);
MultipartBody.Part part = MultipartBody.Part.createFormData("selfie", "xxxx", fileBody);
facePresenter.uploadFrontFace(faceApiKey, faceApiSecret, part,
new FaceHttpCallback<FaceFrontValidateModel>(mActivity, false) {
@Override
public void onSuccess(FaceFrontValidateModel result) {
}
@Override
public void onFailure(FaceHttpError error) {
}
});
}
public void uploadFrontFace(@Part("api_key") RequestBody api_key, @Part("api_secret") RequestBody api_secret, @Part MultipartBody.Part file,
FaceHttpCallback<FaceFrontValidateModel> httpCallback) {
Observable observable = FaceHttpClient.getInstance(false)
.create(FaceService.class)
.uploadFrontFace(api_key, api_secret, file);
toSubscribe(observable).subscribe(httpCallback);
//正脸验证
@POST("lite/raw/validate_front_face")
@Multipart
Observable<FaceFrontValidateModel> uploadFrontFace(@Part("api_key") RequestBody api_key,
@Part("api_secret") RequestBody api_secret,
@Part MultipartBody.Part face);
上传文件时,需要把文件转换为字节流才可以,并且根据其格式进行解析 RequestBody.create(MediaType.parse("image/jpeg"), photos); 要想彻底搞清这些类型和一些参数,应该对http的原理有所了解,和最原始的get 、post 进行文件上传的写法及原理,可以参考 get 、post 请求