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); 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()); } });
为了支持返回值解析,这里我采用了泛型,在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()); } });
- 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); }
下载
你可以像下面这样下载一个文件,但是由于下载的内容都在内存中,所以不支持大文件下载,否则会OOM
String desFileDir = Environment.getExternalStorageDirectory().getAbsolutePath(); OkHttpProxy.download(URL_DOWMLOAD, new DownloadListener(desFileDir, "json.jar") { @Override public void onUIProgress(Progress progress) { 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
灵感来源
本项目的灵感和部分代码来自于下面两个开源项目,谢谢他们的分享精神
尊重原创,转载请注明:From 凯子哥(http://blog.csdn.net/zhaokaiqiang1992) 侵权必究!
关注我的微博,可以获得更多精彩内容
0 0