1、Retrofit入门介绍
Retrofit作为现在最流行的联网框架,公司项目中基本全部使用的它,当然网上有很多详细的教程讲解retrofit的使用,我只是结合自己在项目中的使用情况做一下记录,以便自己日后使用。
1.1 项目安装
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'
1.2 官方教程链接
http://square.github.io/retrofit/
1.3 使用
- 1. 创建Retrofit实例时需要通过Retrofit.Builder,并调用baseUrl方法设置URL。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:4567/")
.build();
2、定义的service返回值为Call的情况
2.1、 Retrofit初始化
public static final String baseUrl = "http://192.168.100.214:8090/peakBusiness/"; //内网
public static final String imgUrl = "http://192.168.100.214:8686/FYmanage/"; //内网--图片
//--接口请求
private static NetworkService api;
public static NetworkService api() {
if (api == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
api = retrofit.create(NetworkService.class);
}
return api;
}
//---上传图片
private static NetworkService apiUpload;
public static NetworkService apiUpload() {
if (apiUpload == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(imgUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiUpload = retrofit.create(NetworkService.class);
}
return apiUpload;
}
2.2、 Retrofit接口方法
我们定义的service返回值为Call的情况。
示例:
//提交投诉或意见
@GET("front/user.htm")
Call<ReceiveData.BaseResponse> upUserBack(@QueryMap Map<String, String> options);
//上传图片
@Multipart
@POST("uploadImg.html")
Call<ReceiveData.UpPhotoResponse> uploadPic(@QueryMap Map<String, String> options, @PartMap Map<String, RequestBody> params);
2.3、 Retrofit返回数据解析
//基础数据的返回
public static class BaseResponse {
public int code;
public String msg;
}
//上传头像
public static class UpPhotoResponse {
public String code;
public String status;
public ArrayList<PiclistBean> piclist;
}
3、定义的service返回值为Observable 的情况
3.1、 Retrofit初始化
HttpMethods.java
public static final String BASE_URL = "http://192.168.100.132:8080/cnbsExamInterface/";
private static final int DEFAULT_TIMEOUT = 15;
private NetworkService networkService;
public static final int SuccessCode = 0;
private String username = "user";
private String password = "123";
// basic认证信息
String credentials = username + ":" + password;
final String basic = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
//构造方法私有,添加一个拦截器
private HttpMethods() {
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Authorization", basic);
return chain.proceed(builder.build());
}
})
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.build();
networkService = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(httpClient)
.build()
.create(NetworkService.class);
}
//在访问HttpMethods时创建单例
private static class SingletonHolder {
private static final HttpMethods INSTANCE = new HttpMethods();
}
//获取单例
public static HttpMethods getInstance() {
return SingletonHolder.INSTANCE;
}
private void toSubscribe(Observable o, Subscriber s) {
o.subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
.subscribe(s);
}
/**
* 下面是请求方法*/
public void base(Subscriber<HttpResult.BaseResponse> subscriber, Map<String, String> options) {
Observable observable = networkService.base(options);
toSubscribe(observable, subscriber);
}
//智能组卷 --zuo
public void autoMakeExam(Subscriber<HttpResult.BaseResponse<MakeExamBean>> subscriber, Map<String, String> options) {
Observable observable = networkService.autoMakeExam(options);
toSubscribe(observable, subscriber);
}
//提交考试信息 --zuo
public void submitExamData(Subscriber<HttpResult.BaseMsgResponse> subscriber, Map<String, String> options, Map<String, RequestBody> params) {
Observable observable = networkService.submitExamData(options,params);
toSubscribe(observable, subscriber);
}
3.2、 请发起求的Service
NetworkService.java
//智能组卷 --zuo
@GET("examAct/intelligencePaperAnswer.html")
Observable<HttpResult.BaseResponse<MakeExamBean>> autoMakeExam(@QueryMap Map<String, String> options);
//提交考试信息 --zuo
@Multipart
@POST("examAct/addUserExam.html")
Observable<HttpResult.BaseMsgResponse> submitExamData(@QueryMap Map<String, String> options, @PartMap Map<String, RequestBody> params);
3.3、 Retrofit返回数据解析
HttpResult.java
public static class BaseResponse<T> {
public int code;
public String msg;
public T obj;
}
public static class BranchResponse{
public int code;
public String msg;
public List<String> list;
}
3.4、 Retrofit使用
private void login(String userId, String password) {
Map<String, String> map = new HashMap<>();
map.put("userId",userId);
map.put("password",password);
HttpMethods.getInstance().base(new Subscriber<HttpResult.BaseResponse>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(HttpResult.BaseResponse baseResponse) {
}
},map);
}
4、Retrofit结合RxJava处理嵌套请求
4.1 Observable模式下的Retrofit实例化
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
4.2 Observable模式下的请求接口
我们定义的service返回值就不在是一个Call了,而是一个Observable:
public interface NetworkService {
@GET("uploadImg.html")
Observable<Bean> uploadPic(@QueryMap Map<String, String> options);
}
4.3 进行网络请求
Map<String, String> options = new HashMap<>();
options.put("key", "value");
RestClient.mapi().request(options)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Bean>() {
@Override
public void onCompleted() {
//----
}
@Override
public void onError(Throwable e) {
//---
}
@Override
public void onNext(MovieEntity movieEntity) {
//----
}
});
4.4 嵌套网络请求
这里就要用到RxJava的操作符flatMap了。Demo代码如下:
Map<String, String> options = new HashMap<>();
options.put("type", "userHeadImg");
Map<String, RequestBody> obj = new HashMap<>();
RequestBody photo = RequestBody.create(MediaType.parse("image/png"), os.toByteArray());
obj.put("Imgs\"; filename=\"icon.png", photo);
RestClient.oapi().oUploadPic(options,obj)
.flatMap(new Func1<ReceiveData.OUpPhotoResponse, Observable<ReceiveData.OBaseResponse>>() {
@Override
public Observable<ReceiveData.OBaseResponse> call(ReceiveData.OUpPhotoResponse oUpPhotoResponse) {
thumPath = oUpPhotoResponse.piclist.get(0).getImg_path();
Map<String, String> options = new HashMap<>();
options.put("method", "updateImg");
options.put("userId", 5+"");
options.put("headImg",thumPath);
return RestClient.omapi().oResetUserImg(options);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ReceiveData.OBaseResponse>() {
@Override
public void call(ReceiveData.OBaseResponse oBaseResponse) {
if (oBaseResponse.code == 0){
showInfo.setText("嵌套请求成功!!");
userimg.setImageURI(RestClient.imgUrl+thumPath);
}
}
});
5、 其他工具类
拦截器InterceptorUtils.java
public class InterceptorUtils{
public static String TAG = "zuo";
//日志拦截器
public static Interceptor LogInterceptor() {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
LogUtils.i(TAG, String.format("接口请求 %s on %s%n%s", request.url(), chain.connection(), request.headers()));
return chain.proceed(request);
}
};
}
//给请求添加一个头
public static Interceptor HeaderInterceptor() {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("token", "zuo");
return chain.proceed(builder.build());
}
};
}
}
日志工具类LogUtils.java
/**
* 日志打印工具类,
* 应用正式上线的时候,需要把LEVEL设置为NOTHING
* author: zuo
* date: 2017/12/5 19:05
*/
public class LogUtils {
public static final int VERBOSE = 1;
public static final int DEBUG = 2;
public static final int INFO = 3;
public static final int WARN = 4;
public static final int ERROR = 5;
public static final int NOTHING = 6;
public static final int LEVEL = VERBOSE;
public static void v(String tag, String msg) {
if (LEVEL <= VERBOSE) {
Log.v(tag, msg);
}
}
public static void d(String tag, String msg) {
if (LEVEL <= DEBUG) {
Log.d(tag, msg);
}
}
public static void i(String tag, String msg) {
if (LEVEL <= INFO) {
Log.i(tag, msg);
}
}
public static void w(String tag, String msg) {
if (LEVEL <= WARN) {
Log.w(tag, msg);
}
}
public static void e(String tag, String msg) {
if (LEVEL <= ERROR) {
Log.e(tag, msg);
}
}
}
6、 Basic认证
有两种添加方式,一种是在每一个接口中加;第二种是在拦截器中加
6-0、 认证信息加密
// 认证信息用Base64编码
String credentials = username + ":" + password;
final String basic =
"Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
6-1、 在接口中加basic认证
这样就是在每次调用接口时都需要传6-0的(String )basic
@GET("loginAct/loginByVerifyCode.html")
Observable<HttpResult.BaseResponse> base(@Header("Authorization") String auth,@QueryMap Map<String, String> options);
6-2、 在拦截器中加basic认证
在拦截器中加的话就简单一点,不需要每个接口都传一遍,这个工作就由拦截器去做了。
public class InterceptorUtils{
public static String TAG = "zuo";
//日志拦截器
public static Interceptor LogInterceptor(final String basic) {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
builder.addHeader("Authorization", basic);
LogUtils.i(TAG, String.format("接口请求 %s on %s%n%s", request.url(), chain.connection(), request.headers()));
return chain.proceed(builder.build());
}
};
}
//给请求添加一个头
public static Interceptor HeaderInterceptor(final String basic) {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Authorization", basic);
// builder.addHeader("token", "zuo");
return chain.proceed(builder.build());
}
};
}
}
/**
* 封装Retrofit的请求
*
* @author zuo
* @date 2017/12/5 16:43
*/
public class HttpMethods {
public static final String BASE_URL = "http://192.168.100.132:8080/cnbsExamInterface/";
private static final int DEFAULT_TIMEOUT = 15;
private NetworkService networkService;
public static final int SuccessCode = 0;
private String username = "user";
private String password = "123";
// basic认证信息
String credentials = username + ":" + password;
final String basic = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
//构造方法私有
private HttpMethods() {
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(InterceptorUtils.LogInterceptor(basic))
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.build();
networkService = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(httpClient)
.build()
.create(NetworkService.class);
}
//在访问HttpMethods时创建单例
private static class SingletonHolder {
private static final HttpMethods INSTANCE = new HttpMethods();
}
//获取单例
public static HttpMethods getInstance() {
return SingletonHolder.INSTANCE;
}
private void toSubscribe(Observable o, Subscriber s) {
o.subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
.subscribe(s);
}
//----------请求方法------------
public void base(Subscriber<HttpResult.BaseResponse> subscriber, Map<String, String> options) {
Observable observable = networkService.base(options);
toSubscribe(observable,subscriber);
}
}
来源:oschina
链接:https://my.oschina.net/u/4518095/blog/4769138