Android为我们提供了两种 HTTP交互的方式:HttpURLConnection 和 Apache HTTP Client ,虽然两者都支持HTTPS,流的上传下载,设置超时,IPv6和连接池,已足够满足我们各种HTTP请求的需求。但更高效的使用HTTP可以让我们的应用运行更快,更节省流量。因此 OkHttp库 也为此诞生。
OkHttp是一款高效的HTTP库,支持链接同一地址的链接共享一个socket通过连接池来减少响应延迟,还有透明的GZIP压缩,请求缓存等优势。OkHttp 存在以下的特点:
Retrofit 与 OkHttp 共同出自于 Square公司,Retrofit 是对 OkHttp做了一层封装。把网络请求都交给OkHttp,我们只需要通过简单的配置就能使用 Retrofit来进行网络请求了。Retrofit存在的优势:
RxJava 主要为了实现异步,其优点就是能够让异步代码 更加简介,而且随着程序变得越来越复杂,它依然保持简洁(逻辑简洁)
具体三个框架详细的介绍,之前已经介绍过,这里就不再敖述
首先在build.gradle 中添加依赖
implementation 'com.squareup.okhttp3:okhttp:3.11.0' // 必要,okhttp依赖
implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0' //log 拦截器
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' //必要,切换线程时用到
implementation 'io.reactivex.rxjava2:rxjava:2.1.1' //必要 rxjava 依赖
implementation 'com.squareup.retrofit2:retrofit:2.3.0' // 必要retrofit依赖
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' // 必要依赖,和Rxjava结合必须用到
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' // 必要依赖,解析json字符所用
public class okHttp3 {
/**
* 懒汉 安全 加同步
* 私有的静态成员变量 只能声明,不能创建
* 私有的构造方法
* 提供返回实例的静态方法
*/
private static OkHttpClient okHttpClient = null;
private okHttp3(){}
public static OkHttpClient getInstence(){
if(okHttpClient == null){
synchronized (okHttp3.class){
if(okHttpClient == null){
//okHttp 可以缓存数据,指定缓存路径
File sdcache = new File(Environment.getExternalStorageDirectory(),"huancun");
//指定缓存
int chcheSize = 10*1024*1024;
//<<<<<<<<<<<<<<<<<日志显示级别>>>>>>>>>>>>>>>>>>>
HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;
//新建Log拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
LogUtil.i("mylog","OkHttp>>>>>>Message:"+message);
}
});
loggingInterceptor.setLevel(level);
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS) //链接超时
.writeTimeout(20,TimeUnit.SECONDS) //写入超时
.readTimeout(20, TimeUnit.SECONDS) //读取超时
.addInterceptor(loggingInterceptor) //添加log 拦截器
.cache(new Cache(sdcache.getAbsoluteFile(), chcheSize)) //设置缓存
.build();
}
}
}
return okHttpClient;
}
/**
* get请求方法
* @param url
* @param callback
*/
public static void doGet(String url, Callback callback){
//创建OkHttp请求对象
OkHttpClient okHttpClient = getInstence();
//创建Request
Request request = new Request.Builder()
.url(url)
.build();
//得到Call对象
Call call = okHttpClient.newCall(request);
call.enqueue(callback);
}
/**
* Post 提交String
* @param url
* @param callback
*/
public static void doPostToString(String url, String str, Callback callback){
MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(mediaType, str)) //传入RequestBody对象
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(callback);
}
/**
* Post 提交 表单信息
* @param url
* @param params
* @param callback
*/
public static void doPostToForm(String url, Map params , Callback callback){
//创建OkHttpClient对象
OkHttpClient okHttpClient = getInstence();
FormBody.Builder builder = new FormBody.Builder();
//遍历集合
for(String key:params.keySet()){
builder.add(key,params.get(key));
}
//创建Request
Request request = new Request.Builder()
.url(url)
.post(builder.build()) //传入RequestBody对象
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(callback);
}
/**
* Post 提交 流
* @param url
* @param str
* @param callback
*/
public static void doPostToIO(String url,final String str, Callback callback){
RequestBody requestBody = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return MediaType.parse("text/x-markdown; charset=utf-8");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8(str);
}
};
OkHttpClient okHttpClient = getInstence();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(callback);
}
/**
* Post 提交 文件
* @param url
* @param f
* @param callback
*/
public static void doPostToFile(String url, File f, Callback callback){
MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
OkHttpClient okHttpClient = getInstence();
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(mediaType, f))
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(callback);
}
}
先针对 服务器返回的数据格式来创建JavaBean对象
BaseEntity
public class BaseEntity {
private static int SUCCESS_CODE = 200; //成功的code
private int code;
private String message;
private T result;
public boolean isSuccess(){
return getCode() == SUCCESS_CODE;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
}
obTextBean
public class obTextBean {
private String name;
private String desc;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
Retrofit的使用会最终生成代理对象,需要一个接口:
public interface APIFunction {
@GET("searchAuthors") //最终会和 Retrofit中的路径进行拼接,所以该字符串不能以 “/”开头
@Headers("Content-Type:application/x-www-form-urlencoded; charset=utf-8") //防止乱码
Observable>> getBaidu(@Query("name") String name);
}
上述代码,在接口中 设置了 getBaidu的方法,使用了RxJava 框架,这样就可以通过代理对象来调用这个方法了。
对Retrofit 封装:
public class RetrofitFactory {
private static RetrofitFactory mRetrofitFactory;
private static APIFunction mAPIFunction;
private RetrofitFactory(){
OkHttpClient client = okHttp3.getInstence(); //获取上面封装的 OkHttp3 实例
Retrofit mRetrofit = new Retrofit.Builder()
.baseUrl("https://api.apiopen.top/") //指定接口路径
.addConverterFactory(GsonConverterFactory.create()) //添加Gson 转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加RxJava转换器
.client(client) //添加OkHttp
.build();
mAPIFunction = mRetrofit.create(APIFunction.class); // 通过接口创建代理对象
}
public static RetrofitFactory getInstence(){
if(mRetrofitFactory == null){
synchronized (RetrofitFactory.class){
if(mRetrofitFactory == null){
mRetrofitFactory = new RetrofitFactory();
}
}
}
return mRetrofitFactory;
}
public APIFunction API(){
return mAPIFunction;
}
}
使用:
RetrofitFactory.getInstance().API()
.getBaidu("李白")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(BaseEntity aBeanBaseEntity) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
但是我们发现,代码还是有点重复,对于 RxJava 中线程的指定 .subscribeOn(Schedulers.io()),.observeOn(AndroidSchedulers.mainThread()),还有 .subscribe 中的四个重构方法,除了onNext之外, 其他的方法都是在重复出现,所以我们可以对 这两处进行封装。
首先对 指定线程封装:
/**
* 统一线程处理(Observable)
* @param
* @return
*/
public static ObservableTransformer setIO_Obervable(){
return new ObservableTransformer() {
@Override
public ObservableSource apply(Observable observable) {
return observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
-----------------------或者:--------------------------------
/**
* 统一线程处理(Flowable)
* @param
* @return
*/
public static FlowableTransformer setIO_Flowable() { //compose简化线程
return new FlowableTransformer() {
@Override
public Flowable apply(Flowable observable) {
return observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
然后对Observer进行封装:
/**
* 对 Observer(观察者) 除 onNext方法外的其他方法的封装
* @param
*/
public abstract class CommonObserver implements Observer {
private Context mContext;
protected CommonObserver(Context context) {
mContext = context;
}
@Override
public void onSubscribe(Disposable d) {
//这里可以显示进度条
Dialogs.showWaitDialog(mContext,"正在访问...");
LogUtil.i("mylog","----Observer_subscribe---");
}
@Override
public abstract void onNext(T t);
@Override
public void onError(Throwable e) {
//这里用来隐藏进度条或者显示错误提示
LogUtil.i("mylog","----CommonObserverE:"+e.getMessage());
}
@Override
public void onComplete() {
//这里隐藏进度条
Dialogs.hideWaitDialog();
LogUtil.i("mylog","----Observer_complete---");
}
}
最终代码如下:
RetrofitFactory.getInstence().API()
.getBaidu("李白")
.compose(RxJava2.>>setIO_Obervable())
.subscribe(new CommonObserver>>(this) {
@Override
public void onNext(BaseEntity> objectBaseEntity) {
if(objectBaseEntity.isSuccess()){
ArrayList objects = objectBaseEntity.getResult();
for(int i =0;i