Rxjava2+okhttp3+Retrofit2封装

这里是Retrofit构造接口的方式,发现重复代码太多,我在网上找了个库,封装了一下,这是改造前部分接口,上次封装的有局限性,那个是根据接口号区分
如果带后缀就不好使了~

public interface UserServiceApi {
    @POST("api/login")
    Call<Result<User>> login(@Body WechatLoginRequest request);

    @POST("version/version")
    Call<Result<User>> update(@Body Update request);

    @POST("api/logout")
    Call<Result> logout(@Body BaseRequest request);

    @POST("api/user/info")
    Call<Result<User>> getOtherUserInfo(@Body BaseRequest request);
}

封装改造后的api如下

public interface Api {
    String KEY = "data";
    String PATH = "path";

    @FormUrlEncoded
    @POST("{path}")
    Observable<String> runPost(@Path(value = PATH, encoded = true) String path,
                               @Field(KEY) String json);

    @GET("{path}")
    Observable<String> runGet(@Path(value = PATH, encoded = true) String path,
                              @Query(KEY) String json);

    @Streaming
    @GET
    Observable<ResponseBody> downFile(@Url() String url, @QueryMap Map<String, String> maps);

    @Multipart
    //@POST("/")
    @POST
    Observable<ResponseBody> uploadFiles(@Url() String url, @Part() List<MultipartBody.Part> parts);
}

我把请求后缀放到请求实体上,采用注解的形式,测试时最大耗时2毫秒左右,不知道能不能接受这个时间

@Inherited
@Documented
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ObtainPath {
    public String value() default "";
}

然后每一个请求体必须实现这个注解,首先我需要一个通用的请求体,姑且如下

@ObtainPath("")
public class CommonReq implements Serializable {
    //里面可以放通用的请求参数
    //比如渠道,版本号,等
}

现在如何构建接口呢?

比如有如下接口

登录接口:https://api.github.com/user/login
注册接口:https://api.github.com/user/register
列表接口:https://api.github.com/user/list
更新接口:https://api.github.com/user/update
测试接口:https://api.github.com/user/test

这里请求格式是json,我需要构造请求体如下

登录

@ObtainPath("user/login")
public class LoginReq extends CommonReq {
    public String name; // 用户名
    public String password; // 密码
}

注册

@ObtainPath("user/register") // 请求后缀在这里
public class RegisterReq extends CommonReq {
}

列表

@ObtainPath("user/list")
public class ListReq extends CommonReq {
}

更新

@ObtainPath("user/update")
public class UpdateReq extends CommonReq {
}

我觉得请求体肯定是少不掉的.响应体通样如此.
项目接口通用结构如下

可能返回这样
 {
 "code": 1, // 我们后台大佬规定,1是成功,不是http code 200
 "msg": "",
 "data": {}
 }
 
也可能返回这样
 {
 "code": 1, // 我们后台大佬规定,1是成功,不是http code 200
 "msg": "",
 "data": []
 }

抽取通用代码

public class CommonResp implements Serializable {
    public static final long serialVersionUID = 1L;
    public int code;
    public String msg;
    public boolean isSuccess() {
        return code == 1; // 1 成功 -1 失败 -2 退出登录
    }
}

如果data返回的是对象

public class HttpCommonObjResp<T> extends CommonResp {
    private static final long serialVersionUID = 1L;
    public T data; // 我喜欢用public,不用get set 方式获取它
 }

如果data返回的是数组对象,我定义如下

public class HttpCommonResp<T> extends CommonResp {
    public List<T> data;
    public List<T> getDatas() {
        if (data == null) {
            data = new ArrayList<T>();
        }
        return data;
    }
}

到此,通用的请求体,通用的响应体已经全部构造完毕

接下来是调用方式:
比如我们的其中一个接口返回数据如下

{
    "code": 1,
    "msg": "",
    "data": {
        "id": "4",
        "channel": "yingyongbao",
        "vnumber": "10",
        "url": "http://shangjie888.oss-cn-shanghai.aliyuncs.com/release-v1.6.5-yingyongbao.apk",
        "content": "1.修正"
        "platform": "android",
        "force": 0,
        "name": null,
        "switch": "1", // 这尼玛关键字,不知道干嘛使的,我一直没用它,可以不关注它,这个字段鬼知道干嘛的....
        "versionnum": "1.6.5"
    }
}

data对象
我需要把这个对象封装,很多接口,需要很多对象,这里我在封装一个基对象,什么都不干,只实现序列化接口,跳转携带对象好用,不用Parcelable接口,懒得写

public class BaseBean implements Serializable {
    public String channel; // 呵呵
}
public class UpdateResp extends BaseBean {
    public String id;
    // public String channel; // 这个通用的么,给它爹
    public String vnumber;
    public String content;
    public String name;
    public String platform;
}

这里算是封装好一个接口的数据了,姑且叫更新接口,怎么调用?

这里有2种方式
1.你可以获取String 自己手动解析
2.你可以指定返回体data

方式一:

HttpRequestFactory.doPost(new UpdateReq(), new ResultCallbackAdapterIs<String>(this) { // this代表activity
            @Override
            public void doOnError(ApiException ex) {
                super.doOnError(ex); // 这里,activity.isFinishing(); 不会走成功和失败回调的          
            }

            @Override
            public void doOnResponse(String response) {
                super.doOnResponse(response);
                // 自己手动解析
            }
        }, null); // null 这里填的是加载框,如有需要

方式二:

data 是对象,所以用HttpCommonObjResp<T>T就是data对象

HttpRequestFactory.doPost(new UpdateReq(), new ResultCallbackAdapterIs<HttpCommonObjResp<UpdateResp>>(this) {
            @Override
            public void doOnResponse(HttpCommonObjResp<UpdateResp> response) {
                super.doOnResponse(response);
                if (response.isSuccess()) {
                    UpdateResp resp = response.data;
                } else {
                    // error
                }
            }
        }, ll);

如果是这样呢?

{
    "code": 1,
    "msg": "",
    "data":[] // 数组对象,咋弄
}

data 是数组对象,所以用HttpCommonResp<T>T就是data数组对象(集合对象)

HttpRequestFactory.doPost(new UpdateReq(), new ResultCallbackAdapterIs<HttpCommonResp<UpdateResp>>(this) {
            @Override
            public void doOnResponse(HttpCommonResp<UpdateResp> response) {
                super.doOnResponse(response);
                if (response.isSuccess()) {
                    List<UpdateResp> resp = response.data;
                    // 看好了,是List<T>接受
                } else {
                    // error
                }
            }
        }, null); // null这里是加载框,可以不用,但是要有
其中代码关于缓存,暂时并没有处理~~~

这是HttpRequestFactory的核心代码,获取请求后缀

public static <T> void exec(Object obj, ResultCallback<T> mCallback, boolean isPost, ILoadingI mILoadingI) {
        if (obj == null) {
            throw new RuntimeException("请求体不能为空~");
        }
        String pathPostfix = "";
        if (obj instanceof CommonReq) {
            long start = SystemClock.currentThreadTimeMillis();
            CommonReq common = (CommonReq) obj;
            ObtainPath mObtainPath = common.getClass().getAnnotation(
                    ObtainPath.class);
            pathPostfix = mObtainPath.value();
            long end = SystemClock.currentThreadTimeMillis();
            Log.e(TAG, "##解析耗时##" + (end - start) + "##毫秒##" + (end - start) / 1000
                    + "##秒##");
            if (TextUtils.isEmpty(pathPostfix)) {
                throw new RuntimeException("网络请求路径后缀不能为空!~");
            }
        } else {
            throw new RuntimeException("请求类型必须是CommonReq 或者 其子类吆~");
        }

        if (!Network.isConnected(HttpLib.getContext())) {
            // ToastTool.showNetisDead(HttpLib.getContext());
            // 没有网络
            if (mILoadingI != null && mILoadingI.isShowingI()){
                mILoadingI.beginDismiss(); //加载框
            }
            return;
        }
        // 发起网络请求 dowork......
        // ....
        if(isPost){
        HttpRequestManager.doPost(pathPostfix, obj, mCallback,mILoadingI);
        } else {
        HttpRequestManager.doGet(pathPostfix, obj, mCallback,mILoadingI);
        }
 }

用法

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

    dependencies {
                compile 'com.github.majunm.http:http:v1.0.31'
    }

也可以移步github,这个不维护了哈哈哈哈哈
源码下载地址

优化版本

《Rxjava2+okhttp3+Retrofit2封装》 部分日志

    原文作者:TMAC_EAH
    原文地址: https://www.jianshu.com/p/f4952e67f099
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞