开始
/*rx*/
compile 'io.reactivex:rxandroid:1.0.1'
compile 'io.reactivex:rxjava:1.0.14'
/*rx生命周期管理*/
compile 'com.trello:rxlifecycle-components:0.6.1'
/*retorfit 2.1 以及rx适配器*/
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
/*网络抓包 stetho chrome://inspect*/
compile 'com.facebook.stetho:stetho:1.3.1'
compile 'com.facebook.stetho:stetho-okhttp3:1.3.1'
ApiManager
private ApiManager() {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
//添加证书
//.sslSocketFactory(sslSocketFactory)
//必须是设置Cache目录
.cache(cache)
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
//stetho,可以在chrome中查看请求
.addNetworkInterceptor(new StethoInterceptor());
Retrofit.Builder retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create());
retrofit.client(builder.build());
apiService =retrofit.build().create(ApiService.class);
}
以上代码在构造方法中执行,给apiService赋值,apiService是请求接口,在该接口中定义请求的方法。目前我使用过post、get、put、delete等方法以及上传表单。
如果设置了BaseUrl,BaseUrl路径形式:http://host:port/path/
如:http://10.0.0.1:8888/a/b/c/
https://api.github.com/
本文这里的path 路径:“op/create_user”可以简写,当然这里可以把Url写全。
Post请求需要带body ,body是对象型参数,相当于多个Filed,返回类型如果有需要可以指定其泛型为某个对象,那么请求返回时就是该对象,这里没有特别指定,使用 返回时是okHttp3中的responsebody对象。
//@Body:对象型
@POST("op/create_user")
Observable<ResponseBody> createUser(@Body Map<String, String> map);
//@Field:用于POST请求,提交单个数据表单
@FormUrlEncoded //这句注解必须加上,否则通不过
@POST("op/create_user")
Observable<ResponseBody> createUser(
@Field("short_name") String shortName,
@Field("author_email") String authorEmail);
//@FieldMap:用于提交多个数据表单
@FormUrlEncoded
@POST("register")
Observable<ResponseBody> userRegister(@FieldMap Map<String,String> map);
- 使用responsebody.string 可以得到json字符串,需要补货异常,responsebody中包含了成功和错误的消息,如果请求失败,可以解析responsebody中的throwable。
public static String handErrorMessage(Throwable throwable){
String error;
if(throwable instanceof HttpException){
HttpException exception = (HttpException) throwable;
try {
error=exception.response().errorBody().string();
Gson gson=new Gson();
HttpErrorException httpErrorException = gson.fromJson(error, HttpErrorException.class);
Log.e("HttpErrorException",error);
error=httpErrorException.getDescription();
} catch (IOException e) {
e.printStackTrace();
error=e.getMessage();
}
}else{
throwable.printStackTrace();
error=throwable.getMessage();
Log.e("HttpErrorException",error);
}
return error;
}
- 使用方法,传入map 为http 的body请求参数,绑定生命周期.compose(activity.bindToLifecycle()),.throttleFirst(3, TimeUnit.SECONDS)设定三秒内执行一次。如果请求成功,onNext将被执行,使用responseBody.string 就可以得到json返回值,如果失败,onError将被执行,并处理Throwable,如果是网络异常,可以解析throwable得到请求错误的消息,如400,401等。
ApiManager.getInstance().createUser(map)
.subscribeOn(Schedulers.io())
.compose(activity.<ResponseBody>bindToLifecycle())
.throttleFirst(3, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<ResponseBody>() {
@Override
public void onCompleted() {
Log.i(TAG);
}
@Override
public void onError(Throwable e) {
Log.e(TAG,e.getMessage());
listener.error(HttpErrorException.handErrorMessage(e));
}
@Override
public void onNext(ResponseBody responseBody) {
Log.i(TAG);
listener.success(responseBody);
}
});
Put请求
如果请求中需要配置header,使用@Header并传入参数,请求Body使用map 包装键值对比较方便。@path 是将传入的参数替换url中的{user_id}。
@PUT("v1/user/{user_id}")
Observable<ResponseBody> changeLoginPsd(@Header("Authorization") String token,@Path("user_id") String userid, @Body Map<String, String> map);
Get请求
如果url不需要传参数可以直接使用固定的url,否则使用@path替换{xxx}参数,这里返回类型是UserInfo实体类。
@GET("v1/user/{user_id}")
Observable<UserInfo> getUserInfo(@Header("Authorization") String token, @Path("user_id") String userid);
Post上传
上传图片,制定请求为表单multipart,并使用@partMap传入键值对参数。
@Multipart
@POST("http://xxx/")
Observable<ResponseBody> uploadImg(@Header("Authorization") String token, @PartMap Map<String, RequestBody> params);
RequestBody body = RequestBody.create(MediaType.parse("image/png"), imgFile);
Map<String, RequestBody> map = new HashMap<>();
map.put("file\"; filename=\"" + imgFile.getName() + "", body);
try {
ApiManager.getInstance().upImg(map).subscribeOn(Schedulers.io()).compose(this.<ResponseBody>bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ResponseBody>() {
@Override
public void call(ResponseBody responseBody) {
userInfo.setIcon_url(filePath);
ImageUtils.loadCircleImage(SettingPersonalActivity.this, ivUserPhoto,filePath, R.mipmap.avatar1);
}
});
} catch (Exception e) {
Log.e(TAG, e.getMessage());
showToast("update fail");
}
结束:
@Path:所有在网址中的参数(URL的问号前面),如:
http://host:port/api/{id}
@Query:URL问号后面的参数,如:
http://host:port/api/a?access_token={access_token}
@QueryMap:相当于多个@Query
@Field:用于POST请求,提交单个数据
@FieldMap: 相当于多个Field,需要注意的是在前面添加注解标明是表单请求:@FormUrlEncoded
@Body:相当于多个@Field,以对象的形式提交