#一、描述
在这里进行描述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的两个类

重写这个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

</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))//转换层
复制代码