OKHTTP

作者: 要学的东西太多了 | 来源:发表于2018-10-31 10:22 被阅读0次

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);
    }
}

相关文章

网友评论

      本文标题:OKHTTP

      本文链接:https://www.haomeiwen.com/subject/subotqtx.html