Retrofit+RxJava,架构一个合理高效逻辑清晰的网络请求层

         最近公司开发使用了大量新技术和新架构,为了让公司的产品能够很好的兼容6.0(之前的请求层一直使用自己写的HttpClient),通过研究,我们决定使用Retrofit+RxJava的架构重写我们的请求层,Retrofit能够很好的构建出一个REST的客户端,而RxJava是一个异步框架,能够让我们避开繁琐而复杂的主线程和额外线程间的切换,Handler的相互发送,使我们能用直观的角度编写代码,增加代码的可读性,对RxJava不熟悉的朋友可以去看《给 Android 开发者的 RxJava 详解》,里面比较清晰而深入地介绍了RxJava框架。

           现在开始构筑请求层,要实现Retrofit的请求,首先我们需要按照要求写一个接口类,里面使用的一些注解等等的用法将会在下面的代码注释中说明:

/**
 * @author Sentox
 *         Created on 2016/4/14.
 *         描述:Retrofit定义接口类
 */
public interface RequestService {
    /**
     * "@GET"表示是用get的方式发起请求
     * "login?"是请求接口
     * "@Query"表示这是一个参数
     * "Observable<PassportLoginResult>"是结合RxJava应该返回的被观察者对象,其返回的结果的数据结构为“PassportLoginResult”
     * 如果是传统的,可以用“Call<NavigationResult>”进行回调
     * 等效于:http://passport.duodian.drcom.com.cn/appserver/login?uid=4918211f837efa6c54dfdc2ecbeb4c58&applicationid=X5LK9zNR4bdfdcDi&cjinfo=12345&apiver=2.0&userName=100076&password=111111
     **/
    @GET("login?")
    Observable<PassportLoginResult> GetLogin(
            @Query("uid") String appid,
            @Query("applicationid") String applicationid,
            @Query("cjinfo") String cjinfo,
            @Query("apiver") String apiver,
            @Query("userName") String userName,
            @Query("password") String password
    );
//    Call<NavigationResult> GetNavigation(
//            @Query("appid") String appid
//    );

    /**
     * "@POST"表示是用post的方式发起请求
     * "@FormUrlEncoded",发送form-encoded数据,每个键-值对都要被含有名字的@Field注解和提供值的对象所标注
     *     如果希望在发起请求的时候再决定接口的名字,可以用下面注释的方法写,{"方法名(参数)"}写在@POST中,
     * 在下面调用@Path("方法名") String 参数,来动态加入url
     * 等效于:http://passport.duodian.drcom.com.cn:80/appserver/userinfo?加上post出去的键值对“accessToken”=》accessToken
     **/
    @FormUrlEncoded
    @POST("userinfo?")//@POST("{test}?")
    Observable<GetUserInfoResult> PostToGetUserInfo(
            //@Path("test") String test,
            @Field("accessToken") String accessToken,
            @Field("userName") String userName,
            @Field("applicationid") String applicationid,
            @Field("uid") String uid,
            @Field("cjinfo") String cjinfo,
            @Field("apiver") String apiver
    );

    /**
     * @QueryMap 表示将map类型的params对象,转成键值对的形式作为参数传递给后台
     */
    @POST("userinfo?")
    Observable<GetUserInfoResult> MapPostToGetUserInfo(
      @QueryMap Map<String,String> params
    );

    /**
     * "@Headers" 是用于添加Http请求的方法头的,header不能被互相覆盖。所有具有相同名字的header将会被包含到请求中。
     * "@Header" 用于动态添加方法头,可以为空,为空的时候忽略
     *       "@Body" 用于添加数据结构,该对象将会被Retroofit实例指定的转换器转换,如果没有添加转换器,
     * 则只有RequestBody可用。请求时根据转换器进行序列化后发送
     * **/
    @Headers({
            "Accept: application/vnd.github.v3.full+json",
            "User-Agent: Retrofit-Sample-App"
    })
    @POST("users/new")
    Call<GetUserInfoResult> createUser(
            @Body GetUserInfoResult user,
            @Header("Authorization") String authorization                           );


}

          在上面的接口类编写成功之后,我们将对这些接口进行调用,这时候我们可以创建一个单例类,来方便整个app进行调用,而不需要每次调用接口在创建一个新的对象,其代码如下:

/**
 * @author Sentox
 *         Created on 2016/4/14.
 *         描述:Retrofit接口调用管理类(单例)
 */
public class RetrofitRequestTool {
    public static RetrofitRequestTool instance;
    public static String BASE_URL = "后台访问的公共地址";

    private RequestService service;

    /**转换器

     * 默认情况下,Retrofit只能够反序列化Http体为OkHttp的ResponseBody类型,并且只能够接受ResponseBody类型的参数作为@body。
     * 添加转换器可以支持其他的类型,为了方便的适应流行的序列化库,Retrofit提供了六个兄弟模块:
     * Gson: com.squareup.retrofit:converter-gson
     * Jackson: com.squareup.retrofit:converter-jackson
     * Moshi: com.squareup.retrofit:converter-moshi
     * Protobuf: com.squareup.retrofit:converter-protobuf
     * Wire: com.squareup.retrofit:converter-wire
     * Simple XML: com.squareup.retrofit:converter-simplexml
     **/
    private RetrofitRequestTool(){
        Retrofit.Builder builder = new Retrofit.Builder();
        Retrofit retrofit = builder
                //基础url
                .baseUrl(BASE_URL)
                //用于Json数据的转换,需要compile 'com.squareup.retrofit2:converter-gson:2.0.0',非必须
                .addConverterFactory(GsonConverterFactory.create())
                //用于返回Rxjava调用,需要 compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0',非必须
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        service = retrofit.create(RequestService.class);
    }

    public static RetrofitRequestTool getInstance(){
        if (instance == null){
            synchronized (RetrofitRequestTool.class){
                if(instance == null){
                    instance = new RetrofitRequestTool();
                }
            }
        }
        return instance;
    }

    public void getLogin(String userName,String password,Subscriber<PassportLoginResult> subscriber){
        service.GetLogin("918211f837efa6c54dfdc2ecbeb4c58","X5LK9zNR4bdfdcDi","","2.0",userName,password)
        .observeOn(AndroidSchedulers.mainThread())//观察者在主线程运行(更新ui)
        .subscribeOn(Schedulers.newThread())//被观察者在新线程运行(发送请求)
        .subscribe(subscriber);
    }

    public void postToGetUserInfo(String accessToken,Subscriber<GetUserInfoResult> subscriber){
        service.PostToGetUserInfo(accessToken, "100076", "X5LK9zNR4bdfdcDi", "4918211f837efa6c54dfdc2ecbeb4c58", "123456", "2.0")
                .observeOn(AndroidSchedulers.mainThread())//观察者在主线程运行(更新ui)
                .subscribeOn(Schedulers.newThread())//被观察者在新线程运行(发送请求)
                .subscribe(subscriber);
    }

    public void MappostToGetUserInfo(Map<String,String> map,Subscriber<GetUserInfoResult> subscriber){
        service.MapPostToGetUserInfo(map)
                .observeOn(AndroidSchedulers.mainThread())//观察者在主线程运行(更新ui)
                .subscribeOn(Schedulers.newThread())//被观察者在新线程运行(发送请求)
                .subscribe(subscriber);
    }
}

          到这里我们的请求层架构已经基本完成了,下面就是在需要的地方调用已经写好的接口:

RetrofitRequestTool.getInstance().MappostToGetUserInfo(map, new Subscriber<GetUserInfoResult>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(GetUserInfoResult getUserInfoResult) {
                if (getUserInfoResult.getResultMsg().getCode().equals("0")) {
                    tv.setText(getUserInfoResult.getMainAccMsg().getNickName());
                } else {
                    Toast.makeText(VolleyTestActivity.this, "getUserInfoResult" + getUserInfoResult.getResultMsg().getMsg(), Toast.LENGTH_LONG).show();
                }
            }
        });
一个请求层框架就这样完成了,欢迎指正。

你可能感兴趣的:(android,retrofit,rxjava,请求层)