Retrofit + RxJava详细教程

#一、描述
在这里进行描述Retrofit和RxJava的使用方法,在刚发现这两种技术的时候,我也是一脸懵逼,这是啥玩意?然后看了很多的教程发现真的好难理解,大多数都是把例子写出来就完了,也没有解释具体是什么含义,对于刚接触的新手来说,学习成本太高,所以这里就给大家通俗的解释一下。

#二、使用说明

####(一)Gradle依赖包

compile 'com.squareup.retrofit2:retrofit:2.0.2'
//基本的依赖,想要用这个网络请求框架,就要添加这个依赖
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
//应用拦截器
compile 'com.squareup.okhttp3:okhttp:3.2.0'
//Retrofit的底层网络访问是使用的okhttp,所以这个也是必须添加的
compile 'com.squareup.okio:okio:1.8.0'
//这个是okhttp所用到的依赖库
compile 'com.google.code.gson:gson:2.6.2'
//Retrofit序列化与反序列化所用到的库(可替换)
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
//与gson对应,用于初始化Retrofit 的(可替换)
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'io.reactivex:rxandroid:1.1.0'
//rest框架的响应式Rx支持库
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
复制代码

####(二)注解说明

####RxJava语法

observables 被观察者(事件源) subscribers 观察者 schedulers 子线程、主线程切换的调度 器,schedulers.newThread() 在子线程中执行,schedulers.mainThread()在主线程中执行,还有io(),computation(),immediate() map 用来操作observable和最终的subscriber之间修改observable发出事件的类型,比如发出类型为int类型,最终为String类型,中间用map来转换 from 能够达到遍历数组的效果,将数组中的元素依次显示 filter 得到大于或者小于某个数的值 take得到前几位值 takelast得到后几位值 deitinct 对一个值只处理一次

####RxJava练习

package wlj.com.rxandroid;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;


/**
 * rxandroid 练习
 * rxjava 练习
 *
 * @author wlj
 * @date 2016/8/5
 */
public class MainActivity extends AppCompatActivity {

    private String TAG = "MainActivity";
    String[] names = {"111", "222", "333"};
    String[][] arrs = {{"11", "12"}, {"21", "22"}, {"31", "32"}};
    String[] nums = {"1", "2", "3", "3", "4", "6"};

    /**
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        ObservableCreate();
//        ObservableSimple();
//        ObservableJust();
//        ObservableRange();
//        ObservableThread();
//        ObservableMap();
//        ObservableFrom();
//        ObservableFlatMap();
//        ObservableFilter();
//        ObservableTake();
        ObservableTest();
    }

    /**
     * rxandroid 练习
     * 需求:
     * 1 给出任意一组数字字符串数组
     * 2 去的重复的数字
     * 3 得到大于1的数字
     * 4 只保留前三位
     * 5 运行在子线程中
     * 6 进行输出
     */
    private void ObservableTest() {
        Observable.from(nums)
                .map(new Func1<String, Integer>() {
                    @Override
                    public Integer call(String s) {
                        return Integer.parseInt(s);
                    }
                })
                .distinct()
                .filter(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer > 1;
                    }
                })
                .take(3)
                .observeOn(Schedulers.newThread())
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.d(TAG, " 当前数字为:" + integer);
                    }
                });
    }


    /**
     * take 截取前面几个元素
     */
    private void ObservableTake() {
        Observable.just(1, 2, 2, 2, 5, 4).take(4).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.d(TAG, "当前数字为:" + integer);
            }
        });
    }

    /**
     * filter 过滤我们不想要的值
     */
    private void ObservableFilter() {
        Observable
                .just(0, 1, 2, 3, 3, 4, 6, 7, 100)
                .filter(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer > 5;
                    }
                })
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.d(TAG, "当前数字为:" + integer);
                    }
                });
    }

    /**
     * 遍历双列的集合数组方式
     */
    private void ObservableFlatMap() {
        Action1<String> action1 = new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG, s);
            }
        };
        Observable
                .from(arrs)
                .flatMap(new Func1<String[], Observable<String>>() {
                    @Override
                    public Observable<String> call(String[] strings) {
                        return Observable.from(strings);
                    }
                })
                .subscribe(action1);
    }

 /**
   * 引用
   */
    private void ObservableFrom() {
        Observable
                .from(names)
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        return "我是:" + s;
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.d(TAG, s);
                    }
                });
    }

    private void ObservableMap() {
        Action1<String> action1 = new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG, s);
                Log.d(TAG, Thread.currentThread().getName());
            }
        };
        Observable
                .just(0, 1, 2, 3, 4)
                .map(new Func1<Integer, String>() {
                    @Override
                    public String call(Integer integer) {
                        return integer.toString();
                    }
                })
                .observeOn(Schedulers.newThread())
                .subscribe(action1);
    }

    /**
     * 调度的使用
     */
    private void ObservableThread() {
        Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                Log.d(TAG, "你被调用了 :" + Thread.currentThread().getName());
                subscriber.onNext("你被调用了1");
            }
        });
        Action1 action1 = new Action1() {
            @Override
            public void call(Object o) {
                Log.d(TAG, "主人有什么吩咐:" + Thread.currentThread().getName());
            }
        };
        observable
                .observeOn(Schedulers.newThread())
                .subscribe(action1);
    }

    private void ObservableRange() {
        Observable.range(0, 10).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.d(TAG, "call :" + integer);
            }
        });
    }

    private void ObservableJust() {
        Observable.just(0, 1, 2).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.d(TAG, "call : " + integer);
            }
        });
    }

    /**
     * 简单用法
     */
    private void ObservableSimple() {
        Observable<String> mObservable = Observable.just("主人下午好");
        mObservable.subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG, s);
            }
        });
    }

    /**
     * 复杂用法
     */
    private void ObservableCreate() {
        //创建一个观察者
        final Subscriber<String> mSubscriber = new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable throwable) {

            }

            @Override
            public void onNext(String s) {
                Log.d(TAG, s);
            }
        };
        //创建被观察者

        Observable<String> mObservable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                mSubscriber.onNext("下午好");
            }
        });
        //被观察者绑定观察者
        mObservable.subscribe(mSubscriber);
    }
}
复制代码

####Retrofit 配置

@Query : 用于Get方法传递参数所用

@Field : 用与Post方法传递参数所用

@Body : 用于Post传递实体类所用

@Headers("apikey:fcedb879f9347de2bd186ef714342231")

@Get : 需要传入他的

HttpServise

public interface HttpService {

@FormUrlEncoded
@POST("PostPhp.php")
Observable<Object> getMessage(@Field("userName") String userName);

}
复制代码

Api类

public class Api {
    private static final String BASEURL = "http://192.168.254.158/FirstTest/src/"; //根地址

    private static final int DEFAULT_TIMEOUT = 10; //超时时间

    private static Api api;

    private final Retrofit retrofit;

    public Api() {
//        Gson gson = new GsonBuilder()
//                .setLenient()
//                .create();
        retrofit = new Retrofit.Builder()
                .baseUrl(BASEURL)
                .client(initHttpClient())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))//异步IO请求
                .addConverterFactory(GsonConverterFactory.create())//转换层
//                .addConverterFactory(GsonConverterFactory.create(gson))//转换层
                .build();
    }

    public static Api getInstance() {
        if (api == null) {
            api = new Api();
        }
        return api;
    }

    /**
     * 描述:初始化OkHttpClient
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/11/17 11:09
     */
    private OkHttpClient initHttpClient() {
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(getApplicationInterceptor()); //添加应用拦截器
        httpClient.retryOnConnectionFailure(false); //错误重联,失败重试
        httpClient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); //连接超时
        httpClient.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); //写入超时
        httpClient.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); //读取超时
        httpClient.addNetworkInterceptor(getNetWorkInterceptor());//网络拦截器
        return httpClient.build();
    }

    /**
     * 描述:内存不足的情况,可以使用以下代码释放内存
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/12/15 11:58
     */
    private void closeMemory(OkHttpClient okHttpClient) {
        okHttpClient.dispatcher().executorService().shutdown();   //清除并关闭线程池
        okHttpClient.connectionPool().evictAll();                 //清除并关闭连接池
        try {
            okHttpClient.cache().close();                             //清除cache
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 描述:返回应用拦截器
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/12/15 11:53
     */
    private Interceptor getApplicationInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return interceptor;
    }

    /**
     * 描述:返回网络拦截器
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/12/15 14:14
     */
    private Interceptor getNetWorkInterceptor() {
        Interceptor authorizationInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {

                Request request = chain.request();
                long t1 = System.nanoTime();
                Log.d(TAG, String.format("Sending request %s on %s%n%s", request.url(),
                        chain.connection(), request.headers()));

                Response response = chain.proceed(request);
                long t2 = System.nanoTime();
                Log.d(TAG, String.format("Received response for %s in %.1fms%n%s",
                        response.request().url(), (t2 - t1) / 1e6d, response.headers()));

                return response;
            }
        };
        return authorizationInterceptor;
    }

    /**
     * 描述:返回对象
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/8/23 10:29
     */
    public <T> T getRetrofit(Class<T> httpServiceClass) {
        return retrofit.create(httpServiceClass);
    }
}
复制代码

自定义请求和接收的转换器,能够在请求后返回的时候,先一步做一些操作 ``` .addConverterFactory(GsonConverterFactory.create())//转换层
可以复制GsonConverterFactory的代码,重写他里面的代码,重写里面的Response和Request的两个类

![](http://upload-images.jianshu.io/upload_images/2650372-b5f4aaebacc12b56.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

重写这个Convert方法,就可以对返回回来的ResponseBody 进行先一步的解析,他这里返回T,你可以更新他返回String都可以,value.string()方法就能获取到服务端返回来的Json字符串了。
复制代码

@Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { return adapter.read(jsonReader); } finally { value.close(); } }

</br>


Api工具类

复制代码

public class ApiUtils {

/**
 * 描述:调用Oauth
 * 作者:卜俊文
 * 邮箱:344176791@qq.com
 * 创建时间: 2016/12/15 19:34
 */
public static <T extends BaseModel, K extends Object> void postOauthRequest(T data, final Class<K> targer, final OnCommondRequestListener onCommondRequestListener) {
    postCommond(data, targer, onCommondRequestListener, Api.RETROFIT_TYPE_OAUTH);
}

/**
 * 描述:调用Cpf
 * 作者:卜俊文
 * 邮箱:344176791@qq.com
 * 创建时间: 2016/12/15 19:34
 */
public static <T extends BaseModel, K extends Object> void postCpfRequest(T data, final Class<K> targer, final OnCommondRequestListener onCommondRequestListener) {
    postCommond(data, targer, onCommondRequestListener, Api.RETROFIT_TYPE_CPF);
}

/**
 * 描述:执行通用Post方法,第一个参数是数据,第二个是对应的接口
 * 作者:卜俊文
 * 邮箱:344176791@qq.com
 * 创建时间: 2016/12/15 15:08
 */
public static <T extends BaseModel, K extends Object> void postCommond(T data, final Class<K> targer, final OnCommondRequestListener onCommondRequestListener, int type) {
    if (data == null) {
        return;
    }
    String info = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(data);
    KLog.e("发送JSON:" + info);

    //组装Header
    String header = getHearder(info, data.getHTTP_SERVER(), data.isRequestEncryptionInterface() ? true : false, type);

    //组装RequestBody
    RequestBody requestBody = getRequestBody(info, data.isRequestEncryptionInterface() ? true : false);

    //请求需要一个Heaeder和RequestBody
    Api.getInstance().getRetrofit(HttpService.class, type)
            .ehomeCommondPost(header, requestBody)
            .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Object>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    onCommondRequestListener.onRequestFail(e.getMessage());
                }

                @Override
                public void onNext(Object o) {
                    KLog.e("返回" + o.toString());
                    String content = StringUtils.contentDecryption(o.toString(), false);
                    K k = null;
                    if (content.startsWith("{")) {
                        //对象
                        k = new Gson().fromJson(content, targer);
                    } else if (content.startsWith("[")) {
                        //集合
                        try {
                            JSONArray jsonArray = new JSONArray(content);
                            List<K> list = new ArrayList<K>();
                            for (int i = 0; i < jsonArray.length(); i++) {
                                list.add(new Gson().fromJson(jsonArray.get(i).toString(), targer));
                            }
                            k = (K) list;
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    } else {
                        onCommondRequestListener.onRequestFail(content);
                        KLog.e("错误:" + content);
                        return;
                    }
                    onCommondRequestListener.onRequestSuccess(k);
                }
            });
}

/**
 * 描述:返回Header
 * 作者:卜俊文
 * 邮箱:344176791@qq.com
 * 创建时间: 2016/12/15 15:17
 */
public static String getHearder(String info, String ehomeAcLoginGet, boolean b, int type) {
    if (type == Api.RETROFIT_TYPE_CPF) {
        return StringUtils.headerInfo(info, ehomeAcLoginGet, b);
    } else if (type == Api.RETROFIT_TYPE_OAUTH) {
        return StringUtils.headerInfo4Update(info, ehomeAcLoginGet, b);
    }
    return null;
}

/**
 * 描述:返回RequestBody
 * 作者:卜俊文
 * 邮箱:344176791@qq.com
 * 创建时间: 2016/12/15 15:19
 */
public static RequestBody getRequestBody(String info, boolean b) {
    String content = StringUtils.contentEncryption(info, b);
    return RequestBody.create(MediaType.parse("application/octet-stream"), content.getBytes());
}
复制代码

}


</br>
##三、异常问题解决
</br>
复制代码

//这个问题在使用Post请求的时候会出现 Caused by: java.lang.IllegalArgumentException: @Field parameters can only be used with form encoding

解决方法:添加注解  @FormUrlEncoded

![](http://upload-images.jianshu.io/upload_images/2650372-554e18c4714dc1ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
</br>
复制代码

//这个问题是因为服务端传下的Json字符串不正确,转换的时候出了问题 onErrorUse JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $

解决方法 :

1 修改服务端传下的Json字符串,让他规范。

2 修改以下代码
复制代码

Gson gson = new GsonBuilder() .setLenient() .create(); .addConverterFactory(GsonConverterFactory.create(gson))//转换层

复制代码

转载于:https://juejin.im/post/5b3ac852e51d4555611997d9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值