OKHTTP流程:
- 初始化OkHttpClient对象,在构造方法里面用默认的Builder对象进行初始化,也可以用builder来构建,builder的cache可以为OKHttp指定缓存方式,框架提供了默认的Cache对象,只需要传入缓存文件和大小即可。
- 初始化request对象,设置url、请求方式、请求数据、请求头等;
- okHttpClient.newCall(request).enqueue(callback)方法,实际上是realcall对象执行enqueue方法,然后往任务队列里面插入asynccall(继承NamedRunnable类,它实现了runnable接口)任务,并由线程池去执行asynccall,调用其execute方法,通过
- getResponseWithInterceptorChain()方法拿到结果并进行回调。这里是调用了一系列的拦截链,可以自定义ResponseBody并添加NetworkInterceptor来实现自己的处理逻辑。
OKHTTP一般需要自行封装,全局用一个对象,且需要用到handler来更新UI,因为回调都在子线程中。
常见用法如下:
public class HttpUtils {
private static volatile HttpUtils h;
private static final int TIME_OUT = 30;
private OkHttpClient mClient;
private Gson mGson;
private IProgressUpdate mIProgressUpdate;
private static final String CACHE_PATH = BaseApp.getInstance().getApplicationContext().getFilesDir().getParent() + "/httpCache/";
private HttpUtils(){
if (h != null) {
throw new RuntimeException("禁止反射");
}
mGson = new Gson();
initClient();
}
public static HttpUtils getInstance(){
if(h==null){
synchronized (HttpUtils.class){
if(h==null){
h = new HttpUtils();
}
}
}
return h;
}
public void setIProgressUpdate(IProgressUpdate IProgressUpdate) {
mIProgressUpdate = IProgressUpdate;
}
public void removeProgressUpdate(){
mIProgressUpdate = null;
}
private void initClient(){
if(mClient==null) {
File file = new File(CACHE_PATH);
if(!file.exists()){
file.mkdirs();
}
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(TIME_OUT,TimeUnit.SECONDS)
.cache(new Cache(file,20 * 1024 * 1024));
builder.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder()
.body(new ProcessResponseBody(response.body(), new ProcessResponseBody.ProgressListener() {
@Override
public void update(int progress) {
if(mIProgressUpdate!=null){
mIProgressUpdate.update(progress);
}
}
}))
.build();
}
});
mClient = builder.build();
}
}
public Disposable requestGet(String url, ICallBack callBack){
return request(url,null,callBack);
}
public <T>Disposable requestPost(String url,T data,ICallBack callBack){
return request(url,mGson.toJson(data),callBack);
}
public <T>Disposable requestPost(String url, List<T> data,ICallBack callBack){
return request(url,mGson.toJson(data),callBack);
}
public Disposable request(String url, String postData, ICallBack callBack) {
Request.Builder builder = new Request.Builder().url(url);
if (postData != null) {
RequestBody body = RequestBody.create(MediaType.parse("application/json ; charset=utf-8"), postData);
builder.post(body);
}
Request request = builder.build();
Flowable flowable = Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
mClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
LogUtils.LogE("接口失败", e.getLocalizedMessage());
emitter.onError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
switch (response.code()) {
case 200:
String result = response.body().string();
LogUtils.LogI("接口成功", result);
if (TextUtils.isEmpty(result)) {
emitter.onError(new Throwable("未获取到数据"));
} else {
emitter.onNext(result);
}
break;
case 500:
LogUtils.LogI("接口失败", "服务器错误");
emitter.onError(new Throwable("服务器错误"));
break;
case 403:
LogUtils.LogI("接口失败", "服务器拒绝请求");
emitter.onError(new Throwable("服务器拒绝请求"));
break;
default:
LogUtils.LogI("接口失败", "请求失败");
emitter.onError(new Throwable("请求失败"));
break;
}
emitter.onComplete();
}
});
}
}, BackpressureStrategy.ERROR).map(new Function<String, HttpData>() {
@Override
public HttpData apply(String s) throws Exception {
return mGson.fromJson(s, HttpData.class);
}
}).observeOn(AndroidSchedulers.mainThread());
Disposable disposable = flowable.subscribe(new Consumer<HttpData>() {
@Override
public void accept(HttpData httpData) throws Exception {
switch (httpData.getRetCode()) {
case HttpData.SUCCESS_CODE:
callBack.success(httpData.getRetObject());
break;
default:
callBack.failure(httpData.getRetMessage());
break;
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
callBack.finish();
callBack.failure(throwable.getMessage());
}
}, new Action() {
@Override
public void run() throws Exception {
callBack.finish();
}
});
return disposable;
}
public void cancelAll(){
mClient.dispatcher().cancelAll();
}
public interface ICallBack{
void finish();
void failure(String errorMsg);
void success(String dara);
}
public static abstract class absCallBack implements ICallBack{
@Override
public void finish() {}
}
public interface IProgressUpdate{
void update(int progress);
}
}
ProcessResponseBody继承自ResPonseBody,可以监听进度:
public class ProcessResponseBody extends ResponseBody {
private ResponseBody mResponseBody;
private ProgressListener mProgressListener;
private BufferedSource mBufferedSource;
public ProcessResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
mResponseBody = responseBody;
mProgressListener = progressListener;
}
@Override
public MediaType contentType() {
return MediaType.parse("application/json ; charset=utf-8");
}
@Override
public long contentLength() {
return 0;
}
@Override
public BufferedSource source() {
if(mBufferedSource==null){
mBufferedSource = Okio.buffer(getSource(mResponseBody.source()));
}
return mBufferedSource;
}
private Source getSource(Source source){
return new ForwardingSource(source) {
long totalBytesRead = 0L;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
if(mProgressListener!=null){
mProgressListener.update((int)((100*totalBytesRead)/mResponseBody.contentLength()));
}
return bytesRead;
}
};
}
public interface ProgressListener{
void update(int progress);
}
}
网友评论