详细属性参考:
https://www.jianshu.com/p/0b6b2d3c862f
https://blog.csdn.net/carson_ho/article/details/73732076
添加请求头参数:
- Headers
用于添加固定请求头,可以同时添加多个。通过该注解添加的请求头不会相互覆盖,而是共同存在
//使用@Headers添加单个请求头
@Headers("Cache-Control:public,max-age=120")
@GET("mobile/active")
Call<ResponseBody> getActive(@Query("id") int activeId);
- Header
作为方法的参数传入,用于添加不固定值的Header,该注解会更新已有的请求头
@GET("mobile/active")
Call<ResponseBody> getActive(@Header("token") String token,@Query("id") int activeId);
用拦截器给全局添加:
动态添加Header:
@Override
public Response intercept(Chain chain) throws IOException {
//给Header里添加参数
Request.Builder builder = chain.request().newBuilder();
CheckBean checkBean = SharedPreferencesHelper.getInstance().getObjectValue("CheckBean", CheckBean.class);
String token = checkBean != null ? checkBean.getAccess_token() : null;
//header()方法如果Header里已经存在该key会替换该key的值,addHeader()则不会替换
if (!StringUtils.isEmpty(token)) builder.header("accessToken", token);
return chain.proceed(builder.build());
}
在url地址里动态追加参数:
String token = DataHolder.getInstance().getToken();
Request originalRequest = chain.request();
HttpUrl originalHttpUrl = originalRequest.url();
HttpUrl.Builder builderUrl = originalHttpUrl.newBuilder();
Request request;
if (!StringUtils.isEmpty(token)) {
builderUrl.addQueryParameter("access_token", token);
HttpUrl newUrl = builderUrl.build();
request = originalRequest.newBuilder().url(newUrl).method(originalRequest.method(), originalRequest.body()).build();
} else {
request = originalRequest.newBuilder().build();
}
return chain.proceed(request);
动态设置Url:
在请求参数里设置@Url
/**
* 发送验证码
*/
@GET
Observable<ResultsMsg> sendCode(@Url String url,@Query("mobile") String mobile);
注意事项:
设置@Url以后,请求参数里不能再配合@Path注解去填补缺省值了,必须要在url里给全请求地址,但是可以配合@Query等使用
网络请求:
- GET请求
GET请求用@Query/@QueryMap填充参数
/**
* 发送验证码
*/
@GET(API.SMS_SEND)
Observable<ResultsMsg> smsSend(@Query("phone") String phone);
/**
* 查询更多课程
*/
@GET(API.QUERY_MORE_COURSE)
Observable<ResultsMsg<List<CommonBean>>> queryMoreCourse(@QueryMap Map<String, Object> stringMap);
- POST请求
POST请求用@Field/@FieldMap填充参数,并且要注明@FormUrlEncoded,否则会请求失败
/**
* 验证码登录
*/
@POST(API.CODE_LOGIN)
@FormUrlEncoded
Observable<ResultsMsg<LoginBean>> codeLogin(@Field("phone") String phone, @Field("code") String code);
/**
* 登录
*/
@POST(API.LOGIN)
@FormUrlEncoded
Observable<ResultsMsg<LiveBean>> login(@FieldMap Map<String,Object> objectMap);
用Json方式提交请求参数:
请求参数必须要用@Body标记
/**
* 登录校验
*/
@POST(API.CHECK)
@Headers({"Content-Type:application/json", "Accept:application/json"})
Observable<ResultsMsg<CheckBean>> check(@Body Map<String, Object> stringMap);
下载文件:
/**
* 下载文件,Range参数为断点续传
*/
@Streaming
@GET
Call<ResponseBody> downloadFile(@Url String url, @Header("Range") String range);
调用下载文件接口:
long progress = file.exists() ? file.length() : 0;
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.xxx.com")
//通过线程池获取一个线程,指定callback在子线程中运行。
.callbackExecutor(Executors.newSingleThreadExecutor())
.build();
RequestApi requestApi = retrofit.create(RequestApi.class);
Call<ResponseBody> call = requestApi.downloadFile(url, "bytes=" + progress + "-");
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull final Response<ResponseBody> response) {
//将Response写入到从磁盘中,注意,这个方法是运行在子线程中的
writeResponseToDisk(file, response, downloadListener);
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable throwable) {
downloadListener.onFail("网络错误~");
}
});
private void writeResponseToDisk(File file, Response<ResponseBody> response, DownloadListener downloadListener) {
//从response获取输入流以及总大小
if (response.body() == null) {
downloadListener.onFail(response.raw().toString());
return;
}
long totalLength = response.body().contentLength();
if (!FileUtils.isFileExists(file)) {
UtilsBridge.createOrExistsFile(file);
UtilsBridge.createOrExistsFile(new File(file.getAbsolutePath() + ConstantUtil.TEMP));
} else {
totalLength += file.length();
}
if (!FileUtils.isEnoughForSD(totalLength)) {
LogUtil.d(TAG, "space is not enough");
ThreadUtils.runOnUiThread(() -> ToastUtils.showLongToast(ResUtils.getString(R.string.out_of_memory)));
downloadListener.onFail("out of Memory");
return;
}
LogUtil.d(TAG, " UtilsConstant.TEMP:" + file.getAbsolutePath() + ConstantUtil.TEMP);
writeFileFromIS(file, response.body().byteStream(), totalLength, downloadListener);
}
//将输入流写入文件
@SuppressLint("CheckResult")
private void writeFileFromIS(File file, InputStream is, long totalLength, DownloadListener downloadListener) {
//开始下载
boolean append = file.length() > 0;
downloadListener.onStart();
OutputStream os = null;
long currentLength = file.length();
int sBufferSize = 524288;
try {
os = new BufferedOutputStream(new FileOutputStream(file, append));
byte data[] = new byte[sBufferSize];
int len;
while ((len = is.read(data, 0, sBufferSize)) != -1) {
os.write(data, 0, len);
currentLength += len;
//计算当前下载进度
Log.i(TAG, "currentLength:" + currentLength + "\ttotalLength:" + totalLength);
downloadListener.onProgress((int) (100 * currentLength / totalLength));
}
//下载完成,并返回保存的文件路径
FileUtils.delete(new File(file.getAbsolutePath() + ConstantUtil.TEMP));
downloadListener.onFinish(file);
} catch (IOException e) {
e.printStackTrace();
downloadListener.onFail("IOException");
} finally {
FileUtils.closeQuietly(is, os);
}
}
public interface DownloadListener {
void onStart();//下载开始
void onProgress(int progress);//下载进度
void onFinish(File file);//下载完成
void onFail(String errorInfo);//下载失败
}
断点续传:
注意事项:
解决问题: