一、首先在Module级别的build.gradle文件中添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
implementation 'com.squareup.retrofit2:converter-gson:2.2.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'
implementation 'io.reactivex.rxjava2:rxjava:2.0.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
二、代码面前,一目了然(注释很清楚)
1、支持多主机地址的网络请求类:HttpApi2.java
package com.yonbor.bettermvp.api;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.yonbor.baselib.base.BaseApplication;
import com.yonbor.baselib.utils.NetWorkUtils;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* 支持多主机地址的网络请求类
* yonbor605
*/
public class HttpApi2 {
//读超时长,单位:毫秒
public static final int READ_TIME_OUT = 20000;
//连接时长,单位:毫秒
public static final int CONNECT_TIME_OUT = 20000;
public Retrofit retrofit;
public static ApiService apiService;
private static SparseArray<HttpApi2> httpApi2SparseArray = new SparseArray<>(HostType.TYPE_COUNT);
/*************************缓存设置*********************/
/*
1. noCache 不使用缓存,全部走网络
2. noStore 不使用缓存,也不存储缓存
3. onlyIfCached 只使用缓存
4. maxAge 设置最大失效时间,失效则不使用 需要服务器配合
5. maxStale 设置最大失效时间,失效则不使用 需要服务器配合 感觉这两个类似 还没怎么弄清楚,清楚的同学欢迎留言
6. minFresh 设置有效时间,依旧如上
7. FORCE_NETWORK 只走网络
8. FORCE_CACHE 只走缓存*/
/**
* 设缓存有效期为两天
*/
private static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;
/**
* 查询缓存的Cache-Control设置,为if-only-cache时只查询缓存而不会请求服务器,max-stale可以配合设置缓存失效时间
* max-stale 指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可接收超出超时期指定值之内的响应消息。
*/
private static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_SEC;
/**
* 查询网络的Cache-Control设置,头部Cache-Control设为max-age=0
* (假如请求了服务器并在a时刻返回响应结果,则在max-age规定的秒数内,浏览器将不会发送对应的请求到服务器,数据由缓存直接返回)时则不会使用缓存而请求服务器
*/
private static final String CACHE_CONTROL_AGE = "max-age=0";
// 构造方法私有
private HttpApi2(int hostType) {
//开启Log
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.e("HttpApi", "OkHttpMessage:" + message);
}
});
logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//缓存
File cacheFile = new File(BaseApplication.getAppContext().getCacheDir(), "cache");
Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
//增加头部信息
Interceptor headerInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request build = chain.request().newBuilder()
.addHeader("Content-Type", "application/json") //设置允许请求json数据
.build();
return chain.proceed(build);
}
};
//创建一个OkHttpClient并设置超时时间
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS)
.connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS)
.addInterceptor(mRewriteCacheControlInterceptor) // 自定义的拦截器,用于添加公共参数
.addNetworkInterceptor(mRewriteCacheControlInterceptor)
.addInterceptor(headerInterceptor)
.addInterceptor(logInterceptor)
.cache(cache)
.build();
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").serializeNulls().create();
retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(ApiConstants.getHost(hostType))
.addConverterFactory(GsonConverterFactory.create(gson)) //请求的结果转为实体类
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //适配RxJava2.0,RxJava1.x则为RxJavaCallAdapterFactory.create()
.build();
apiService = retrofit.create(ApiService.class);
}
public static ApiService getApiService() {
HttpApi2 httpApi2 = httpApi2SparseArray.get(0);
if (httpApi2 == null) {
httpApi2 = new HttpApi2(0);
httpApi2SparseArray.put(0, httpApi2);
}
return httpApi2.apiService;
}
public static ApiService getApiService(int hostType) {
HttpApi2 httpApi2 = httpApi2SparseArray.get(hostType);
if (httpApi2 == null) {
httpApi2 = new HttpApi2(hostType);
httpApi2SparseArray.put(hostType, httpApi2);
}
return httpApi2.apiService;
}
/**
* 根据网络状况获取缓存的策略
*/
@NonNull
public static String getCacheControl() {
return NetWorkUtils.isNetConnected(BaseApplication.getAppContext()) ? CACHE_CONTROL_AGE : CACHE_CONTROL_CACHE;
}
/**
* 云端响应头拦截器,用来配置缓存策略
* Dangerous interceptor that rewrites the server's cache-control header.
*/
private final Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String cacheControl = request.cacheControl().toString();
if (!NetWorkUtils.isNetConnected(BaseApplication.getAppContext())) {
request = request.newBuilder()
.cacheControl(TextUtils.isEmpty(cacheControl) ? CacheControl.FORCE_NETWORK : CacheControl.FORCE_CACHE)
.build();
}
Response originalResponse = chain.proceed(request);
if (NetWorkUtils.isNetConnected(BaseApplication.getAppContext())) {
//有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置
return originalResponse.newBuilder()
.header("Cache-Control", cacheControl)
.removeHeader("Pragma")
.build();
} else {
return originalResponse.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_SEC)
.removeHeader("Pragma")
.build();
}
}
};
}
2、主地址(baseUrl)类型管理类:HostType.java
public class HostType {
/**
* 多少种Host类型
*/
public static final int TYPE_COUNT = 2;
/**
* 首页类型host
*/
public static final int HOME_NEW_LIST = 1;
/**
* 图片上传类型host
*/
public static final int PICTURE_NEW_LIST = 2;
}
3、获取对应的主机地址的类:ApiConstants.java
public class ApiConstants {
public static final String BASEURL = "http://www.baidu.com/";
/**
* 获取对应的host
*
* @param hostType host类型
* @return host
*/
public static String getHost(int hostType) {
String host;
switch (hostType) {
case HostType.HOME_NEW_LIST:
host = "http://v.juhe.cn/toutiao/";
break;
case HostType.PICTURE_NEW_LIST:
host = "";
break;
default:
host = "";
break;
}
return host;
}
}
三、如何使用
1、接口类ApiService.java中定义接口
package com.yonbor.bettermvp.api;
import com.yonbor.bettermvp.model.Result;
import com.yonbor.bettermvp.model.ResultModel;
import com.yonbor.bettermvp.model.home.news.NewsListModel;
import java.util.List;
import io.reactivex.Flowable;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface ApiService {
// 聚合新闻头条接口
@GET("index")
Flowable<ResultModel<Result<List<NewsListModel>>>> getNews(@Query("type") String type, @Query("key") String key);
}
2、聚合数据的新闻头条接口的调用
package com.yonbor.bettermvp.ui.app.home.news;
import android.widget.Toast;
import com.yonbor.baselib.base.BasePresenter;
import com.yonbor.bettermvp.api.HostType;
import com.yonbor.bettermvp.api.HttpApi2;
import com.yonbor.bettermvp.model.Result;
import com.yonbor.bettermvp.model.ResultModel;
import com.yonbor.bettermvp.model.home.news.NewsListModel;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import java.util.List;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* @Description:
* @Author: YinYongbo
* @Time: 2018/8/13 15:22
*/
public class NewsListPresenter extends BasePresenter<NewsListView> {
public void getNewsListData() {
Flowable<ResultModel<Result<List<NewsListModel>>>> flowable = HttpApi2.getApiService(HostType.HOME_NEW_LIST).getNews("top", "9d5c5d5de8c5ff12244879da48f5bfb3");
flowable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<ResultModel<Result<List<NewsListModel>>>>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(ResultModel<Result<List<NewsListModel>>> resultResultModel) {
if (resultResultModel.result.data != null) {
List<NewsListModel> list = resultResultModel.result.data;
// String stat = resultResultModel.result.stat;
if (list.size() > 0) {
mView.returnNewsListData(list);
}
} else {
Toast.makeText(mContext, "暂无数据", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
}
}
四、更多代码可前往本人GitHub仓库下载了解。仓库地址:https://github.com/yonbor605/Android-BetterMVP,欢迎star,谢谢!