oKHttp基本封装

来源:互联网 发布:cmd获取软件版本号 编辑:程序博客网 时间:2024/06/08 02:47

需求:

  • get请求和post请求,上传文件和下载文件时返回进度
  • oKHttpClient实例只创建一次
  • 如果用户在结果还未返回时又连续多次请求相同的api,只保留最后一次,前面的中断请求
  • 返回的JSON数据转化成实体对象
  • 访问服务器是异步请求,将请求结果回调到主线程

首先用一个抽象类用于回调

public abstract class ResultCallback {    public abstract void onError(Request request,Exception e);    public abstract void onSuccess(Object str);}

oKHttp无论哪种方式请求都是创建OkHttpClient、Request和Call对象,然后在调用Call的enqueue()方法。

 private volatile static oKHttpEngine mInstance; private oKHttpEngine(){} public static oKHttpEngine getInstance(){        if(mInstance == null){            synchronized (oKHttpEngine.class){                if(mInstance == null){                    mInstance = new oKHttpEngine();                }            }        }        return mInstance;    }

使用单例设计模式,获取类的对象,由于是单例设计模式,所以无论对getInstance()调用多少次都只会创建一个对象

public void setHttpConfig(HttpConfig httpConfig){        this.httpConfig = httpConfig;        client = new OkHttpClient.Builder()                .connectTimeout(httpConfig.getConnectionTimeOut(), TimeUnit.SECONDS)                .readTimeout(httpConfig.getReadTmeOut(),TimeUnit.SECONDS)                .writeTimeout(httpConfig.getWriteTimeOut(),TimeUnit.SECONDS)                .proxy(Proxy.NO_PROXY)                .build();        mHandler = new Handler();        gson = new Gson();}

创建oKHttpClient对象,并设置链接时间,读取时间等信息,此方法必须被调用。并创建Gson对象和Handler对象。

private Call execute(Request.Builder builder,Header[] h, ResultCallback resultCallback,String url){        //设置请求头信息        boolean hasUa = false;        if(h==null){            builder.header("Connection","close");            builder.header("Accept","*/*");        }else {            for (Util.Header header:h){                builder.header(header.getName(),header.getValue());                if(!hasUa&&header.getName().equals("User-Agent")){                    hasUa = true;                }            }        }        if(!hasUa&&!TextUtils.isEmpty(httpConfig.getUserAgent())){            builder.header("User-Agent",httpConfig.getUserAgent());        }        Call call = client.newCall(builder.build());        dealResult(call,resultCallback,url);        return call;    }

首先设置请求头信息,通常不需要设置,通过build()方法创建Request对象,并且创建Call对象

private void dealResult(Call call, final ResultCallback resultCallback, final String url){        call.enqueue(new Callback() {            @Override            public void onFailure(Call call,IOException e) {                sendFailed(call.request(),resultCallback,e);            }            @Override            public void onResponse(Call call, final Response response) throws IOException {                if(resultCallback!=null){                    try {                        String str = response.body().string();                        if(clazz!=null||clazzBean!=null){                            JSONObject jsonObject = new JSONObject(str);                            String strData = jsonObject.toString();                            //用于解析JSON中的数组                            if(info!=null){                                JSONArray jsonArray = jsonObject.getJSONArray(info);                                if(jsonArray.length()>0){                                    for(int i =0;i<jsonArray.length();i++){                                        String content = jsonArray.getJSONObject(i).toString();                                        Object o = gson.fromJson(content,clazz);                                        sendSuccess(o,resultCallback);                                    }                                }                            }                            //用于解析JSON数据中去除数组的部分                            if(clazzBean!=null){                                Object o = gson.fromJson(strData,clazzBean);                                sendSuccess(o,resultCallback);                            }                        }else {                            sendSuccess(str,resultCallback);                        }                    } catch (IOException e) {                        e.printStackTrace();                    }catch (JSONException e){                        e.printStackTrace();                    }                }else {                    try {                        ResponseBody requestBody = ProgressHelper.withProgress(response.body(),progressListener);                        BufferedSource bufferedSource = requestBody.source();                        File file = new File(saveFilePath);                        file.delete();                        file.getParentFile().mkdirs();                        file.createNewFile();                        BufferedSink sink = Okio.buffer(Okio.sink(file));                        bufferedSource.readAll(sink);                        sink.flush();                        bufferedSource.close();                    }catch (Exception e){                        e.printStackTrace();                    }                }            }            private void sendSuccess(final Object o, final ResultCallback resultCallback){                if(resultCallback!=null){                    mHandler.post(new Runnable() {                        @Override                        public void run() {                            resultCallback.onSuccess(o);                        }                    });                }            }            private void sendFailed(final Request request, final ResultCallback resultCallback, final Exception e){                mHandler.post(new Runnable() {                    @Override                    public void run() {                        if(resultCallback!=null){                            resultCallback.onError(request,e);                        }else {                            e.printStackTrace();                        }                    }                });            }        });    }

如果下载文件则不需要设置回调,故ResultCallback设置为null,这里上传和下载文件的监听使用的是开源库https://github.com/lizhangqu/CoreProgress,在请求数据时若返回的是JSON数据,首先解析JSON数组,然后解析非数组的部分。注意这里的数据解析在子线程中运行,当解析完毕后才把数据发送给主线程回调

get请求:

 public void asyncGet(String url,Header[] h,ResultCallback resultCallback,Class clazz,Class clazzBean,String info){        this.clazz = clazz;        this.clazzBean = clazzBean;        this.info = info;        Request.Builder builder = new Request.Builder();        builder.url(url);        Call call = execute(builder,h,resultCallback,url);        add(url,call);    }

post请求:

public void post(String url, Header[] h, ResultCallback resultCallback, List<NameValue> list,Class clazz,Class clazzBean,String info){        if(list == null){             list = new ArrayList<>();        }        this.clazz = clazz;        this.clazzBean = clazzBean;        this.info = info;        list.addAll(httpConfig.getComFiled());        FormBody.Builder form = new FormBody.Builder();        for(NameValue item:list){            form.add(item.getName(),item.getValue());        }        RequestBody requestBody = form.build();        Request.Builder builder = new Request.Builder();        builder.url(url);        builder.post(requestBody);        Call call = execute(builder,h,resultCallback,url);        add(url,call);    }

上传JSON:

public void jsonPost(String url,Header[] h,ResultCallback resultCallback,Map<String,String> map,Class clazz,Class clazzBean,String info){        this.info = info;        this.clazzBean = clazzBean;        this.clazz = clazz;        String str = gson.toJson(map);        MediaType Json = MediaType.parse("application/json; charset=utf-8");        RequestBody requestBody = RequestBody.create(Json,str);        Request.Builder builder = new Request.Builder();        builder.url(url);        builder.post(requestBody);        Call call = execute(builder,h,resultCallback,url);        add(url,call);    }

上传文件:

public void postFile(String url, Header[] h, ResultCallback resultCallback, Set<File> files, Class clazz, Class clazzBean, String info, String key, ProgressUIListener progressUIListener){        this.clazz = clazz;        this.clazzBean = clazzBean;        this.info = info;        MediaType mediaType = MediaType.parse("application/octet-stream");        MultipartBody.Builder mBuilder = new MultipartBody.Builder();        mBuilder.setType(MultipartBody.FORM);        if(files!=null){            for(File file:files){                mBuilder.addFormDataPart(key,file.getName(),RequestBody.create(mediaType,file));            }        }        RequestBody requestBody = null;        if(progressUIListener!=null){//需要回调上传进度            requestBody = ProgressHelper.withProgress(mBuilder.build(),progressUIListener);        }else {//不需要回调上传进度            requestBody = mBuilder.build();        }        Request.Builder builder = new Request.Builder();        builder.url(url);        builder.post(requestBody);        Call call = execute(builder,h,resultCallback,url);        add(url,call);    }

下载文件:

public void downloadFile(String url,Header[] h,ResultCallback resultCallback,String saveFilePath,ProgressUIListener progressUIListener){        this.progressListener = progressUIListener;        this.saveFilePath = saveFilePath;        Request.Builder builder = new Request.Builder();        builder.url(url);        Call call = execute(builder,h,resultCallback,url);        add(url,call);    }
private void add(String url,Call call){        if(!TextUtils.isEmpty(url)){            if(url.contains("?")){                url = url.substring(0,url.indexOf("?"));            }            cancel(url);            map.put(url,call);        }    }    private void cancel(String url){        Call call = map.remove(url);        if(call!=null){            call.cancel();        }    }

首先将URL和Call对象添加到map集合中,当从map中取出Call不为null时则取消请求,在第一次请求时,首先从集合中取出Call对象,由于是第一次请求故Call为null,当进行第二次相同的请求时,此时从集合中取出的是第一次请求的Call对象,故调用cancel()方法取消该请求。

全部代码OKHTTP封装2

原创粉丝点击