Rxjava2+Retrofit2网络框架傻瓜式接入指南

前言

本文主要是介绍本人在项目中接入Rxjava2和Retrofit2的过程中的一些经验心得、遇到的问题,特别是本人的学习曲线,希望能帮助到你。主要的概念介绍涉及较少,但是在文中会给出我在接入的过程中参考过的文章。
之所以把Rxjava2放在前面是因为,我最开始的时候只想接入Rxjava2来体验高大上的响应式编程,但是在学习和接入Rxjava2的过程中,感觉到非常有必要将Retrofit也整合进来,Retrofit的API设计非常适合Rxjava,两者结合使用是最完美的,于是就在项目中同时引用了Rxjava2+Retroif2。从学习到最后完成接入大概耗时5天以上。在这个过程中,自己的编程思想得到了很大的锻炼和提高,从最后使用的结果来看,框架极大的简化了平时做网络请求的步骤,特别是做到了代码的解耦,极大的提高了代码的可阅读性。

在动手之前,建议大家先对MVP模式(http://www.cnblogs.com/changyiqiang/p/6044618.html)、
面向接口编程(http://blog.sina.com.cn/s/blog_6c969b4a0102vnh6.html)有一定认识,
对Retrofit2和Rxjava2(文中用RR代替)有一些基本的了解。
RxJava2.0教程(一)
http://www.jianshu.com/p/464fa025229e.
我所理解的RxJava——上手其实很简单
http://www.jianshu.com/p/5e93c9101dc5

Ok,所谓万事开头难,如果有想法的同学的一定要尽早开始。让我们从导包开始一步步搭建自己的RR框架:

添加Gradle配置:

compile 'io.reactivex.rxjava2:rxjava:2.0.6'   
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'  
compile 'com.squareup.retrofit2:converter-gson:2.2.0'   
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0' 

根据后台提供的接口创建实体类

public class PayMoneyEntity {
    float money ;

    public float getMoney() {
        return money;
    }

    public void setMoney(float money) {
        this.money = money;
    }
}

这里推荐两个的插件:
使用GsonFormat可以根据JSON快速生成实体类
http://blog.csdn.net/dakaring/article/details/46300963
使用Android parcelable code generator可以快速得序列化对象
http://blog.csdn.net/kroclin/article/details/40902721

创建Retrofit对象:

1、先写一个抽象类:

public abstract class BaseService {
    protected  abstract  String getBaseUrl();
    protected Retrofit baseRetrofit(){
        OkHttpClient client=new OkHttpClient.Builder()
                .addInterceptor(new AddPubicParamsInterceptor())//自定义的拦截器,用于添加公共参数
                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))//拦截器,用于日志的打印
                .build();

        Retrofit retrofit=new Retrofit.Builder()
                .client(client)
                .baseUrl(getBaseUrl())
                .addConverterFactory(MyConvert.create())//对获得的结果进行解析和处理,是比较重要的部分,在我的项目中涉及到解密和一些业务逻辑判断
                .addConverterFactory(GsonConverterFactory.create())//默认直接转化为实体类,不会进行解密等处理
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//Retrofit2与Rxjava2之间结合的适配器
                .build();
        return  retrofit;
    }
}

2、定义网络请求的接口:

public interface GetCustomListApi {

    @GET("sample.client/pay/money")//这里是URL的后半段
    Observable<PayMoneyEntity> getPayInfo(@Query("user_id") String user_id);

}

3、管理Retrofit:

public class RestService extends BaseService {
    private static final String BASE_REST_URL = "http://www.baidu.cn:80";//这里是URL的前半段
    @Override
    protected String getBaseUrl() {
        return BASE_REST_URL;
    }
    public GetCustomListApi creatCustomApi(){
        return baseRetrofit().create(GetCustomListApi.class);
    }
}

1、首先我们来看一下Interceptor:
关于拦截器的介绍大家参考:
http://blog.csdn.net/oyangyujun/article/details/50039403

在我们的项目中大部分请求都需要添加公共参数,我们通过自定义的拦截器重写intercept方法即可:

public class AddPubicParamsInterceptor implements Interceptor {

    @SuppressWarnings("deprecation")
    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();
        // 添加公共的新的参数
        HttpUrl.Builder authorizedUrlBuilder = request.url()
                .newBuilder();
        Request.Builder build = request.newBuilder();
        Map<String, Object> globalParams = new HashMap<>();//这里是我们的公共参数,根据自己项目实际情况获得,具体添加什么样的参数,在这里做逻辑判断即可
        Iterator it = globalParams.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            //如果是中文/其他字符,会直接把字符串用BASE64加密,
            String s = URLDecoder.decode(String.valueOf(entry.getValue()));
            authorizedUrlBuilder.addQueryParameter((String) entry.getKey(), s);
        }
    //生成新的请求
        Request newrequest = request.newBuilder()
                .method(request.method(), request.body())
                .url(authorizedUrlBuilder.build())
                .build();

        return chain.proceed(newrequest);
    }
}


2、在定义网络请求接口大家参考:
Retrofit2.0 API使用解析
http://blog.csdn.net/zuck_t/article/details/50718774/
Android网络请求库 - Say hello to retrofit
http://blog.csdn.net/ghost_Programmer/article/details/52372065

这里当时我花费了比较多的时间,因为要找到适合自己项目的URL写法。

3、到了这一步我们终于把请求处理完了,最后让我们来看一下解析GsonConverterFactory——转换器,参考:
Retrofit 2.0 自定义Converter
http://blog.csdn.net/jdsjlzx/article/details/51860663

这里的解析处理也是耗了比较多的时间,特别是遇到一个奇葩的问题非常正常的一行代码一直编译不通过,

 TypeAdapter<?> adapter=gson.getAdapter(TypeToken.get(type));

后来重新安装了AS就没有再现了。来看代码:

public final class MyConvert extends Converter.Factory {
    private final Gson gson;

    public static MyConvert create(Gson gson) {
        return new MyConvert(gson);
    }
    public  static MyConvert create(){
        return create(new Gson());
    }

    public MyConvert(Gson gson) {
        this.gson = gson;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        TypeAdapter<?> adapter=gson.getAdapter(TypeToken.get(type));
        return new DecodeResponseBodyConverter<>(gson,adapter);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter=gson.getAdapter(TypeToken.get(type));
        return new RequestBodyConverter<>(gson, adapter);
    }
}

public class DecodeResponseBodyConverter<T> implements Converter<ResponseBody, T>  {
    private final TypeAdapter<T> adapter;
    private final Gson gson;

    DecodeResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.adapter = adapter;
        this.gson = gson;
    }

    @Override
    public T convert(ResponseBody responseBody) throws IOException {
        try {
            String s = responseBody.string();
            //s就是我们网络请求获得的字符串了,因为我们项目中以前的网络框架用到了把字符串封装为Response对象,为了保持一致和方便维护这里也继续使用Response对象。大家根据自己项目具体情况处理即可。
            Response response=new Response(s);
            //response.content是消息体,这里进行解密处理
            String decodeBody = Utils.decode(response.content, true);

            JsonReader jsonReader = gson.newJsonReader(new StringReader(decodeBody));
            return adapter.read(jsonReader);
        }  finally {
            responseBody.close();
        }

}


自定义的RequestBodyConverter跟GsonConverterFactory中用到的GsonRequestBodyConverter一样,就不贴代码了。

Rxjava2+Rtrofit2完成网络请求:

public class TestActivity extends Activity {
    private GetCustomListApi customListApi = new RestService().creatCustomApi();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        customListApi.getPayInfo(UserDataUtils.getInstance().getUser_id())
                .subscribeOn(Schedulers.io())//线程控制
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<PayMoneyEntity>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }
                    @Override
                    public void onNext(PayMoneyEntity payMoneyEntity) {
                        payMoneyEntity.getMoney();
                    }
                    @Override
                    public void onError(Throwable e) {
                    }
                    @Override
                    public void onComplete() {
                    }
                });
    }

}

线程控制Scheduler 的原理:
http://blog.csdn.net/qq_28195645/article/details/52564494

在OnNext方法中我们就得到了经过解析后的实体类,可以getMoney了,享受长长的准备工作后的成果吧。

结语:

我自己在接入RR框架的过程中确实对自己的编程思想有非常大的提升,也希望更多的人能掌握RR框架的使用,写出更简洁优雅的代码。

猜你喜欢

转载自blog.csdn.net/Jason_Fish/article/details/70075853