最近retrofit + RxJava 请求方式很火啊,本人也对此做了一些封装,也算是对架构的一点实践吧,需要文件如下:
‘HttpService接口 定义每个接口
HttpManager类 处理每个请求
OperResponse类 接口返回的根结构(基于json格式)
BaseOperation类 每一个请求的基类
Retrofit + RxJava请求方式需要这样的一个接口,定义方式如下:
public interface HttpService { @FormUrlEncoded //采用模拟表单方式请求 @POST("user/login/v2")//post请求方式,接口名称 Observable<OperResponse> login(@FieldMap Map<String, String> map);//参数是map集合,发送请求时转换成json发送给服务端 }
接下来是HttpManger的定义:
public class HttpManager { public volatile static HttpManager instance; public HttpService httpService; private NetWorkUtils netWorkUtils; private HttpManager() { //手动创建一个okhttpClient并设置超时时间 OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() .connectTimeout(Config.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.SECONDS)//设置连接超时 .readTimeout(Config.DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS)//设置读超时 .writeTimeout(Config.DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS)//设置写超时 .retryOnConnectionFailure(false);//不可重试 clientBuilder .setLevel(Level.BODY) .log(Platform.INFO) .request("Request") .response("Response") .addHeader("version", "latest") .build()); OkHttpClient client = clientBuilder.build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(Config.ROOT_URL) .addConverterFactory(GsonConverterFactory.create())//设置参数以及返回数据都是json格式 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//采用RxJava的方式进行请求 .client(client)//设置客户端 .build(); httpService = retrofit.create(HttpService.class);//生成httpService对象 } public static HttpManager getInstance() { if (instance == null) { instance = new HttpManager(); } return instance; } /** * 用于activity请求 * * @param operation * @param context */ public void dealHttpResponse(Context context, BaseOperation operation) { if (hasNetwork(context)) { if (operation != null) { operation.handleError(operation.getNoNetResponse()); } return; } Observable observable = operation.getObservable(httpService) .filter(operation.getFilterFunc1())//过滤返回的数据,如果错误直接处理 .map(operation.getMapFun1())//转换对象如OperResponse转换成User .subscribeOn(Schedulers.io())//子线程进行 .compose(((RxAppCompatActivity) context).bindToLifecycle())//与activity周期绑定,act销毁则请求结束,activity必须继承RxAppCompatActivity .observeOn(AndroidSchedulers.mainThread());//转回主线程 observable.subscribe(operation.getSubscriber());//处理数据并结束 } /** * 用于service等非Activity中请求 * * @param operation * @return */ public Subscription dealHttpResponse(BaseOperation operation, Context context) { if (hasNetwork(context)) { return null; } Observable observable = operation.getObservable(httpService) .filter(operation.getFilterFunc1()) .map(operation.getMapFun1()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); return observable.subscribe(operation.getSubscriber()); } private boolean hasNetwork(Context context) { netWorkUtils = NetWorkUtils.getNetWorkUtils(context); return netWorkUtils.getConnectState().equals(NetWorkUtils.NetWorkState.NONE); } }
再就是OperResponse类,因为此封装是基于json格式,如:
public class OperResponse implements Parcelable { public String respcode;// code,200表示返回成功 public String respmsg;// 响应消息 public String data;// 响应的具体的json数据 @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.respcode); dest.writeString(this.respmsg); dest.writeString(this.data); } public OperResponse() { } protected OperResponse(Parcel in) { this.respcode = in.readString(); this.respmsg = in.readString(); this.data = in.readString(); } public static final Creator<OperResponse> CREATOR = new Creator<OperResponse>() { @Override public OperResponse createFromParcel(Parcel source) { return new OperResponse(source); } @Override public OperResponse[] newArray(int size) { return new OperResponse[size]; } }; }接下来最重要的类来了,那就是BaseOperation类,是个抽象类,基于solid架构原则,这个类必须是一个抽象类,如下:下面是具体使用,此种方式的缺点就是每一个请求都需要一个具体的BaseOperation子类,如登录public abstract class BaseOperation<T> { protected RequestListener requestListener; protected Context mContext; public BaseOperation(Context context, RequestListener requestListener) { this.requestListener = requestListener; this.mContext = context; } //获取请求接口 public abstract Observable getObservable(HttpService httpService); //处理返回的数据 public abstract Subscriber<T> getSubscriber(); //处理具体的类型,如response->User等等 public abstract Func1<OperResponse, T> getMapFun1(); //设置个性化的参数 protected abstract Map<String, String> setParam(); //设置共型的参数 protected Map<String, String> getParam() { Map<String, String> map = new HashMap<>(); map.put(Config.RequestParam.REQUEST_PARAM_VERSION, Config.VERSION_INTERFACE); map.put(Config.RequestParam.REQUEST_PARAM_SYSTEM, Config.SYSTEM); map.put(Config.RequestParam.REQUEST_PARAM_APP_VERSION, Util.getAppVersionName(mContext)); map.put(Config.RequestParam.REQUEST_PARAM_OS_VERSION, android.os.Build.VERSION.SDK_INT + ""); Map<String, String> otherParams = setParam(); if (otherParams != null && !otherParams.isEmpty()) { map.putAll(otherParams); } // //发送日志记录 // String content = JsonUtils.requestObjectBean(map); // LogManager.getInstance().sendLog(mContext.getApplicationContext(),content); return map; } public Func1<OperResponse, Boolean> getFilterFunc1() { return new Func1<OperResponse, Boolean>() { @Override public Boolean call(OperResponse operResponse) { return filerData(operResponse); } }; } //过滤返回结果,right or wrong private boolean filerData(OperResponse operResponse) { //发送日志记录 // String content = JsonUtils.requestObjectNullBean(operResponse); // LogManager.getInstance().sendLog(mContext.getApplicationContext(),content); //end if (TextUtils.equals(operResponse.respcode, Config.RequestCode.CODE_SUCCESS)) { //请求成功 return true; } else { handleError(operResponse); return false; } } //处理错误结果 public void handleError(OperResponse operResponse) { if (operResponse == null) { operResponse = getOperResponse(); } Observable.just(operResponse) .subscribeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<OperResponse>() { @Override public void call(OperResponse operResponse) { if (TextUtils.equals(operResponse.respcode, Config.RequestCode.CODE_ERROR_LOGIN_OVERDUE)) { /** * 这两个状态表示登录已过期,跳转到登录页面重新登录 */ Intent intent = new Intent(mContext, LoginActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mContext.startActivity(intent); } else { if (requestListener != null) { requestListener.onFailure(operResponse); } } } }); } public OperResponse getNoNetResponse(){ OperResponse operResponse = new OperResponse(); operResponse.respcode = "104"; operResponse.respmsg = "无网络连接,请连接网络"; return operResponse; } protected OperResponse getOperResponse() { OperResponse operResponse = new OperResponse(); operResponse.respcode = "1000"; operResponse.respmsg = "网络连接超时,请重试。"; return operResponse; } protected OperResponse getParseOperResponse() { OperResponse operResponse = new OperResponse(); operResponse.respcode = "110"; operResponse.respmsg = "解析数据错误"; return operResponse; } }public interface RequestListener<T> { void onSuccess(T t); void onFailure(OperResponse operResponse); }这个类的注释写的也比较清楚,就不过多介绍了,详细介绍一下抽象方法吧,因为在HttpManager中发送请求时是要传入具体的实现类的,比如:LoginOperation,它必须继承BaseOperation类,那么这个抽象类到具体类时,那些会发生变化的方法是要被做成抽象方法的,如使用的每个接口,返回的数据不同等等,都要求方法被抽象化,实际上是使用具体子类的方法返回的数据。
public class LoginOperation extends BaseOperation<User>{
private String phoneNumber; private String password; public LoginOperation(Context context, RequestListener requestListener) { super(context, requestListener); } public LoginOperation(Context context, RequestListener requestListener, String phoneNumber, String password) { this(context, requestListener); this.phoneNumber = phoneNumber; this.password = password; }@Override public Observable getObservable(HttpService httpService) { return httpService.login(getParam()); }/** * 设置参数 * * @return */ @Override public Map<String, String> setParam() { Map<String, String> map = new HashMap<>(); try { String json = JsonUtils.requestObjectBean(new RegisterVoBean.RegisterObj(phoneNumber, password)); map.put("para", data); } catch (Exception e) { e.printStackTrace(); } return map; }@Override public Subscriber<User> getSubscriber() { return new Subscriber<User>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { if (requestListener != null) requestListener.onFailure(getOperResponse()); } @Override public void onNext(User user) { if (userResult != null) requestListener.onSuccess(user); } }; }@Override public Func1<OperResponse, User> getMapFun1() { return new Func1<OperResponse, User>() { @Override public User call(OperResponse operResponse) { User user = null; try { user = JsonUtils.parserJsonStringToObject(operResponse.data, User.class); } catch (Exception e) { //处理异常,json转object错误 // handleError(operResponse); e.printStackTrace(); } return user; } }; }
}
最后在来个门面模式包装一下
public class OperateFactoryManager { private static OperateFactoryManager instance; private OperateFactoryManager() { } public static OperateFactoryManager getInstance() { if (instance == null) { instance = new OperateFactoryManager(); } return instance; }}/** * 登录 * * @param context * @param phoneNumber * @param verifyCode * @param requestListener */ public void login(Context context, String phoneNumber, String password, RequestListener requestListener) { LoginOperation loginOperation = new LoginOperation(context, requestListener, phoneNumber, password); HttpManager.getInstance().dealHttpResponse(context, loginOperation); }
需要的jar如下:
compile 'io.reactivex:rxandroid:1.2.1' //RxAndroid compile 'io.reactivex:rxjava:1.1.6' //RxJava compile 'com.jakewharton.rxbinding:rxbinding:0.4.0' compile 'com.jakewharton.rxbinding:rxbinding-support-v4:0.4.0' compile 'com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.4.0' compile 'com.trello:rxlifecycle-android:0.8.0' compile 'com.trello:rxlifecycle-components:0.8.0' compile 'com.trello:rxlifecycle:0.8.0' compile 'com.google.code.gson:gson:2.6.2' 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'
以上就是我对Retofit+RxJava做的一个简单的封装,还可以对上传和下载也进行这样的封装,这里就不一一介绍了,感兴趣的同学可以看看,如果有更好建议,欢迎交流哈。