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 請求