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

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

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

为了支持返回值解析,这里我采用了泛型,在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());
                    }
                });

你如果想获取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());
                    }
                });

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

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

然后就可以将返回结果解析为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());
            }
        });

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

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

@Override
    protected void onDestroy() {
        super.onDestroy();
        OkHttpProxy.cancel(this);
    }

下载

你可以像下面这样下载一个文件,但是由于下载的内容都在内存中,所以不支持大文件下载,否则会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());
            }
        });
    }

上传

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

灵感来源

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



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

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

时间: 2024-10-03 22:54:18

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

【FTP】FTP文件上传下载-支持断点续传

Jar包:apache的commons-net包: 支持断点续传 支持进度监控(有时出不来,搞不清原因) 相关知识点 编码格式: UTF-8等; 文件类型: 包括[BINARY_FILE_TYPE(常用)]和[ASCII_FILE_TYPE]两种; 数据连接模式:一般使用LocalPassiveMode模式,因为大部分客户端都在防火墙后面: 1. LocalPassiveMode:服务器端打开数据端口,进行数据传输: 2. LocalActiveMode:客户端打开数据端口,进行数据传输: 系统

封装了okhttp的网络框架,支持大文件上传下载,上传进度...

本帖最后由 anjoy紫外线 于 2016-4-20 16:42 编辑   1.用法 对于Eclipse不能运行项目的,提供了apk供直接运行,位于项目根目录 okhttputils_v1.x.x.apk. 本项目Demo的网络请求是我自己的服务器,有时候可能不稳定,网速比较慢时请耐心等待.. 对于Android Studio的用户,可以选择添加: compile 'com.lzy.net:okhttputils:1.3.0'  //可以单独使用,不需要依赖下方的扩展包    compile'c

struts2 实现文件上传下载 (下载支持中文文件名)代码

struts2 实现文件上传: Action 代码: package com.action; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import org.apache.struts2.ServletActionContext; import com.o

Python实现简单的HTTP服务器(支持文件上传下载)

1.python内置模块 SimpleHTTPServer  (支持下载功能) 在对应的工作目录下,运行命令python -m SimpleHTTPServer 即可把当前目录下以共享服务的形式共享出去. 外部访问可通过访问:http://ip:端口号来访问  (默认端口为8000) 可指定端口: python -m SimpleHTTPServer 8081 2.Woof模块 http://www.home.unix-ag.org/simon/woof.html 3.Droopy模块  (支持

C# FTPHelper 支持多层级文件上传下载

在网上找了很多代码总觉得不能满足现有的需求 ,比如多级文件夹,一次性上传不同层级的所有文件.自己将网上找到的代码加上自己的修改.现在贴出来给大家希望呢个对大家有个小小帮助.欢迎找茬,互相进步 /// <summary> /// FTP帮助类 /// </summary> public class FTPHelper { #region 字段 string ftpURI; string ftpUserID; string ftpServerIP; string ftpPassword

web大文件上传解决方案支持分片断点上传

一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输.关闭浏览器后保留进度信息. 支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务器端文件夹层级结构与本地相同. 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验:支持文件夹上传,文件夹中的文件数量达到1万个以上,且包含层级结构. 支持断点续传,关闭浏览器或刷新浏览

网页大文件上传解决方案支持分片断点上传

1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通过浏览器上传至服务器,做一层中转便可以实现,但当这份文件非常大到了10GB级别,我们就需要思考另一种形式的技术方案了,也就是本文要阐述的方案. 技术要求主要有以下几方面: 支持超大数据量.10G级别以上 稳定性:除网络异常情况100%成功 准确性:数据无丢失,读写准确性100% 效率:1G文件分钟级

go语言的一个gui 开源 项目 https://github.com/andlabs/ui

go语言的一个gui 开源 项目  https://github.com/andlabs/ui 1 安装  mingw-w64  链接地址: http://mingw-w64.sourceforge.net/download.php 2 liteide 配置: # native compiler windows 386 GOROOT=c:\go GOBIN=%GOROOT%\bin GOARCH=386 GOOS=windows CGO_ENABLED=1 PATH=C:\Program Fil

在GitHub上创建上传下载开源项目代码

1.注册GitHub帐号,创建GitHub项目代码仓库 1.1.注册GitHub帐号 在使GitHub之前,需要先登录其官网注册一个免费使用的账号.登录 https://github.com/join?source=header-home进行注册. 1.2 在GitHub上添加SSH Key 为什么要在GitHub上添加SSH Key呢?因为 GitHub 需要识别出提交的代码确实是你提交的而不是别人.Git支持SSH协议,因此GitHub只要知道了你的公钥,就可以确认代码是你提交的.当然, G