开源项目OkHttpPlus——支持GET、POST、UI线程回调、JSON格式解析、链式调用、文件上传下载

来源:互联网 发布:阿里云网站备案 编辑:程序博客网 时间:2024/05/22 14:06

OkHttpPlus介绍

项目地址:https://github.com/ZhaoKaiQiang/OkHttpPlus

主要功能:OkHttp封装,支持GET、POST、UI线程回调、JSON格式解析、链式调用、小文件上传下载及进度监听等功能

为什么要写这么一个库呢?

首先,是因为OkHttp在4.4之后已经作为底层的Http实现了,所以OkHttp这个库很强大,值得我们学习。

其次,在我看来,OkHttp使用起来不如Volley方便,OkHttp的回调都是在工作线程,所以如果在回调里面操作View的话,需要自己转换到UI线程,非常繁琐,所以需要封装。也有将OkHttp作为Volley底层Http实现的用法,发送请求、维护请求队列用的是Volley,实际的Http请求用的是OkHttp。

关于Volley和oOkHttp结合的Demo请戳煎蛋项目

如何使用

初始化

你可以在Application里面完成初始化,因为对OkHttp的封装主要使用的是代理设计模式,使用OkHttpProxy.getInstance()可以获取到单例客户端,你可以像没封装之前一样,设置任意的参数,比如下面就设置超时时间和忽略HTTPS认证。

public class OkApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        OkHttpClient okHttpClient = OkHttpProxy.getInstance();        okHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);        okHttpClient.setReadTimeout(15, TimeUnit.SECONDS);        okHttpClient.setWriteTimeout(15, TimeUnit.SECONDS);        //ignore HTTPS Authentication        okHttpClient.setHostnameVerifier(new MyHostnameVerifier());        try {            SSLContext sc = SSLContext.getInstance("TLS");            sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());            okHttpClient.setSslSocketFactory(sc.getSocketFactory());        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (KeyManagementException e) {            e.printStackTrace();        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Get方法

你大多数情况下是和OkHttpProxy这个代理类打交道,而且OkHttpPlus支持链式调用,内部采用Builder设计模式,所以你可以像下面这样使用

 OkHttpProxy.get()                .url(URL_USER)                .tag(this)                .execute(new OkCallback<User>(new OkJsonParser<User>() {                }) {                    @Override                    public void onSuccess(int code, User user) {                        tv_response.setText(user.toString());                    }                    @Override                    public void onFailure(Throwable e) {                        tv_response.setText(e.getMessage());                    }                });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

为了支持返回值解析,这里我采用了泛型,在OkCallback的构造函数中,你需要传入一个解析器,OkHttpPlus内部支持5种解析器,这可以解决你大部分的需求

  • OkBaseParser,所有解析器的基类,不可直接使用
  • OkBaseJsonParser,所有JSON解析器的基类,你可以继承它来定义自己的JSON解析
  • OkJsonParser,JSON解析器,支持JSONObject和JSONArray的解析,默认使用GSON作为解析器
  • OkTextParser,String解析器,支持将结果以String方式输出
  • OkFileParser,文件解析器,支持将结果保存为文件,你可以用来下载文件,但是不支持较大文件下载

所以如果你想获取一个JSONArray,你可以像下面这样

 OkHttpProxy.get()                .url(URL_USER)                .tag(this)                .execute(new OkCallback<List<User>>(new OkJsonParser<List<User>>() {                }) {                    @Override                    public void onSuccess(int code, List<User> users) {                        tv_response.setText(users.toString());                    }                    @Override                    public void onFailure(Throwable e) {                        tv_response.setText(e.getMessage());                    }                });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

你如果想获取String数据,你可以这样

  OkHttpProxy.get()                .url(URL_BAIDU)                .tag(this)                .execute(new OkCallback<String>(new OkTextParser()) {                    @Override                    public void onSuccess(int code, String s) {                        tv_response.setText(s);                    }                    @Override                    public void onFailure(Throwable e) {                        tv_response.setText(e.getMessage());                    }                });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

当然,如果你想自定义一个解析器,也是完全可以的。

OkHttpPlus的解析器部分使用的是策略设计模式,所以你可以像下面这样自定义一个解析策略,完成结果的解析

public class JokeParser<T> extends OkJsonParser<T> {    @Nullable    @Override    public T parse(Response response) throws IOException {        String jsonStr = response.body().string();        try {            jsonStr = new JSONObject(jsonStr).getJSONArray("comments").toString();            return mGson.fromJson(jsonStr, new TypeToken<ArrayList<Joke>>() {            }.getType());        } catch (JSONException e) {            e.printStackTrace();            return null;        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

然后就可以将返回结果解析为ArrayList了

  OkHttpProxy.get()                .url(Joke.getRequestUrl(1))                .tag(this).execute(new OkCallback<List<Joke>>(new JokeParser()) {            @Override            public void onSuccess(int code, List<Joke> jokes) {                tv_response.setText(jokes.toString());            }            @Override            public void onFailure(Throwable e) {                tv_response.setText(e.getMessage());            }        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Post方法

Post的方法与Get方法使用类似,你可以像下面这样发送POST请求,并添加Header和Params。

 OkHttpProxy                .post()                .url(URL_USERS)                .tag(this)                .addParams("name", "zhaokaiqiang")                .addHeader("header", "okhttp")                .execute(new OkCallback<ArrayList<User>>(new OkJsonParser<ArrayList<User>>() {                }) {                    @Override                    public void onSuccess(int code, ArrayList<User> users) {                        tv_response.setText(users.toString());                    }                    @Override                    public void onFailure(Throwable e) {                        tv_response.setText(e.getMessage());                    }                });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

你可能注意到了,在发送每个请求的时候,我都调用了tag()方法,所以你可以在不需要的时候,将请求取消掉。

@Override    protected void onDestroy() {        super.onDestroy();        OkHttpProxy.cancel(this);    }
  • 1
  • 2
  • 3
  • 4
  • 5

下载

你可以像下面这样下载一个文件,但是由于下载的内容都在内存中,所以不支持大文件下载,否则会OOM

 String desFileDir = Environment.getExternalStorageDirectory().getAbsolutePath();        OkHttpProxy.download(URL_DOWMLOAD, new DownloadListener(desFileDir, "json.jar") {            @Override            public void onUIProgress(Progress progress) {                //当下载资源长度不可知时,progress.getTotalBytes()为-1,此时不能显示下载进度                int pro = (int) (progress.getCurrentBytes() / progress.getTotalBytes() * 100);                if (pro > 0) {                    pb.setProgress(pro);                }                KLog.d("pro = " + pro + " getCurrentBytes = " + progress.getCurrentBytes() + " getTotalBytes = " + progress.getTotalBytes());            }            @Override            public void onSuccess(File file) {                tv_response.setText(file.getAbsolutePath());            }            @Override            public void onFailure(Exception e) {                tv_response.setText(e.getMessage());            }        });    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

上传

OkHttpPlus也支持小文件上传,我这里测试使用的是七牛的上传API,Token是有期限的,所以你需要在下面网址自己生成测试

 /**     * 采用七牛上传接口,Token有效期为12小时,若Token无效,请在下面自行获取     * Token生成网址 http://jsfiddle.net/gh/get/extjs/4.2/icattlecoder/jsfiddle/tree/master/uptoken     * <p/>     * AK = IUy4JnOZHP6o-rx9QsGLf9jMTAKfRkL07gNssIDA     * CK = DkfA7gPTNy1k4HWnQynra3qAZhrzp-wmSs15vub6     * BUCKE_NAME = zhaokaiqiang     */    public void uploadFile(View view) {        File file = new File(Environment.getExternalStorageDirectory(), "jiandan02.jpg");        if (!file.exists()) {            Toast.makeText(MainActivity.this, "文件不存在,请修改文件路径", Toast.LENGTH_SHORT).show();            return;        }        Map<String, String> param = new HashMap<>();        param.put("token", TOKEN);        Pair<String, File> pair = new Pair("file", file);        OkHttpProxy                .upload()                .url(URL_UPLOAD)                .file(pair)                .setParams(param)                .setWriteTimeOut(20)                .start(new UploadListener() {                    @Override                    public void onSuccess(Response response) {                        tv_response.setText("isSuccessful = " + response.isSuccessful() + "\n" + "code = " + response.code());                    }                    @Override                    public void onFailure(Exception e) {                        tv_response.setText(e.getMessage());                    }                    @Override                    public void onUIProgress(Progress progress) {                        int pro = (int) ((progress.getCurrentBytes() + 0.0) / progress.getTotalBytes() * 100);                        if (pro > 0) {                            pb.setProgress(pro);                        }                        KLog.d("pro = " + pro + " getCurrentBytes = " + progress.getCurrentBytes() + " getTotalBytes = " + progress.getTotalBytes());                    }                });    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

灵感来源

本项目的灵感和部分代码来自于下面两个开源项目,谢谢他们的分享精神

  • okhttp-utils
  • CoreProgress

尊重原创,转载请注明:From 凯子哥(http://blog.csdn.net/zhaokaiqiang1992) 侵权必究!

关注我的微博,可以获得更多精彩内容

0 0
原创粉丝点击