OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据
OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据
我们这片博文就来聊聊这个反响很不错的OkHttp了,标题是我恶搞的,本篇将着重详细的分析,探索OkHttp这个框架的使用和封装
一.追其原理
Android系统提供了两种HTTP通信类
- HttpURLConnection
- HttpClient
Google推荐使用HttpURLConnection,这个没必要多说,事实上,我这篇写的应该算是比较晚了,很多优秀的博文都已经提出了这些观点了,那我也就不好意思重复的说废话了,不过我还是得吐槽一下,HttpURLConnection是在是太难用了,而且功能也实在是太少了,虽然Github上封装的框架还真是不少,不过依然不是特别好用,而Google自己也在寻求解决的办法,如果你看过android4.4的源码,你就应该知道,Google把HttpURLConnection替换成了OkHttp,而OkHttp走到现在,已经是相对来说,比较成熟的框架了,那我们为何不去使用它呢?而且现在学习OkHttp的资料和文章实在是太多了,根本不需要什么学习成本的,搜索一下,马上就有一大堆,既然如此,我们今儿个就来看看这个花姑凉长什么样吧!各位小司机,跟着老司机一起上车吧!
注意,我们使用的IDE是Android Studio
二.使用准备
肯定要配置一下啦,我们首先新建一个工程——OkHttpGo,这名字好听,我就不加demo或者test了,这样显得有点low,项目我们基于5.0 Lollipop来开发
而关于OkHttp的官方介绍,大家可以移步这里
- http://square.github.io/okhttp/
如果想看源码,可以去Github上
- https://github.com/square/okhttp
我们既然要使用,就根据github上来吧,加入依赖,把依赖添加到build.gradle中,当然,他是提供jar的,你如果用Eclipse获取喜欢用jar,你也可以直接下载jar
compile 'com.squareup.okhttp3:okhttp:3.3.1'
因为我们会用到图片解析,所以可以加上Picasso的依赖,关于它的介绍,可以移步
- http://square.github.io/picasso/
这个库,我下篇博文会介绍到,这里你只要知道是这么添加依赖和使用就可以了
compile 'com.squareup.picasso:picasso:2.5.2'
记住,网络的使用,是需要添加权限的哦!
<!--网络权限--><uses-permission android:name="android.permission.INTERNET"/>
行,大致的配置就到这里OK了,如果你还有什么不清楚的,可以去他们官网或者github上瞧一瞧,看一看,这里再送上一下下载jar的地址吧!
- OkHttp 2.7.5 Jar下载
OkHttp内部依赖了Okio,这里也提供了jar下载地址
- Okio 1.8.0 jar下载
三.图片加载
我们先从图片加载说起,最起码先定义一下布局呀
<ImageViewandroid:id="@+id/iv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/ic_launcher" /><Buttonandroid:id="@+id/btn_iv"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="图片加载" />
非常简陋的一个布局,就一个button和一个imageview,现在我们就是点击按钮,然后解析显示在控件上,这对于OkHttp来说,应该是怎么使用的呢?注意,现在演示的,都还只是没有封装的前提下,我们首先做一些准备工作
//成功状态private static final int SUCCESS_STATUS = 1;//失败状态private static final int FAIL_STATUS = 2;//图片链接private String url = "http://d.3987.com/qiz_141118/004.jpg";
这里我定义了两个常量,分别是解析成功失败的状态,又定义了一张图片的链接,图片是网上的以上美女图片,好的,这些都准备好了,现在我们就可以来书写OkHttp相关的类了
//图片解析btn_iv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//初始化OkHttpOkHttpClient client = new OkHttpClient();//构建Request,解析链接,这里可选get/post方法final Request request = new Request.Builder().get().url(url).build();//添加到请求队列client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {//失败Log.i(TAG, "解析失败");}@Overridepublic void onResponse(Call call, Response response) throws IOException {//成功Message message = handler.obtainMessage();//判断,成功就传值if (response.isSuccessful()) {message.what = SUCCESS_STATUS;message.obj = response.body().bytes();handler.sendMessage(message);} else {handler.sendEmptyMessage(FAIL_STATUS);}}});}});
可以看到,它使用和Volley有点类似,个人感觉,其实也就是那么几个步骤,首先初始化,然后设置一下乱七八糟的属性,最后添加到队列中,返回两个回调,成功和失败,是吧,我们这个时候就直接用handler去发消息了
//子线程private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case SUCCESS_STATUS://拿值byte[] result = (byte[]) msg.obj;//图片加载Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);//设置图片iv.setImageBitmap(bitmap);break;case FAIL_STATUS://失败Log.i(TAG, "解析失败");break;}}};
得出来的效果,用一张图来表示就绰绰有余了
OK,图片解析的就已经实现了
四.图片裁剪
现在呢,我们可以看到是一个美女的图片,但是如果我们图片比较大,而我们不需要这么大,比如长这样?
如果我们不想要这么大的图片,又或者说,我们想要一张正方形一样整齐的图片,我们该怎么去做?还记得我们添加的picasso图片框架吗?他就可以做到,我们可以用它的功能写一个工具类来帮助我们裁剪,这个工具类写起来也没有多麻烦
package com.lgl.okhttpgo;import android.graphics.Bitmap;import com.squareup.picasso.Transformation;/*** 裁剪图片* Created by LGL on 2016/6/19.*/
public class TailorImageView implements Transformation {@Overridepublic Bitmap transform(Bitmap source) {//得到原图片的大小,取最小值int size = Math.min(source.getWidth(), source.getHeight());//长大于宽,还是宽大于长int x = (source.getWidth() - size) / 2;int y = (source.getHeight() - size) / 2;//创建新的bitmapBitmap bitmap = Bitmap.createBitmap(source, x, y, size, size);if (bitmap != source) {//回收source.recycle();}return bitmap;}@Overridepublic String key() {return "lgl";}
}
我们使用的话,就在我们解析成功的时候调用就可以了,
case SUCCESS_STATUS://拿值byte[] result = (byte[]) msg.obj;//图片加载Bitmap bitmap = new TailorImageView().transform(BitmapFactory.decodeByteArray(result, 0, result.length));//设置图片iv.setImageBitmap(bitmap);break;
我们可以是这样的
正方形就搞定了,欧耶!
五.网络框架封装
事实上,我们上面所说的,都还是有些许繁杂了,毕竟我们不应该重复的去写这么多麻烦的代码,对吧,现在我们来对他进行一个封装,而对于OkHttp,他有以下的几个功能
- 一般的get请求
- 一般的post请求
- 基于Http的文件上传
- 文件下载
- 加载图片
- 支持请求回调,直接返回对象,对象集合
- 支持session的保持
我们要封装一个OkHttp的话,也就是围绕着他的这几个功能来二次开发了,好的,小司机们,我们继续开车吧!污污污污污…..
我们写一个OkHttpUtils,其实还算是比较简单的,因为我们实际上没写多少内容
package com.lgl.okhttpgo;import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;import org.json.JSONException;
import org.json.JSONObject;import java.io.IOException;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;/*** OkHttp的封装工具类* Created by LGL on 2016/6/19.*/
public class OkHttpUtils {//TAGprivate static final String TAG = OkHttpUtils.class.getSimpleName();//声明客户端private OkHttpClient client;//防止多个线程同时访问所造成的安全隐患private volatile static OkHttpUtils okHttpUtils;//定义提交类型Jsonprivate static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");//定义提交类型Stringprivate static final MediaType STRING = MediaType.parse("text/x-markdown;charset=utf-8");//子线程private Handler handler;//构造方法private OkHttpUtils() {//初始化client = new OkHttpClient();handler = new Handler(Looper.getMainLooper());}//单例模式public static OkHttpUtils getInstance() {OkHttpUtils okUtils = null;if (okHttpUtils == null) {//线程同步synchronized (OkHttpUtils.class) {if (okUtils == null) {okUtils = new OkHttpUtils();okHttpUtils = okUtils;}}}return okUtils;}/*** 请求的返回结果是json字符串** @param jsonValue* @param callBack*/private void onsuccessJsonStringMethod(final String jsonValue, final FuncJsonString callBack) {handler.post(new Runnable() {@Overridepublic void run() {if (callBack != null) {try {//解析jsoncallBack.onResponse(jsonValue);} catch (Exception e) {}}}});}/*** 求的返回结果是json对象** @param jsonValue* @param callBack*/private void onsuccessJsonObjectMethod(final String jsonValue, final FuncJsonObject callBack) {handler.post(new Runnable() {@Overridepublic void run() {if (callBack != null) {try {callBack.onResponse(new JSONObject(jsonValue));} catch (JSONException e) {e.printStackTrace();}}}});}/*** 求的返回结果是json数组** @param data* @param callBack*/private void onsuccessJsonByteMethod(final byte[] data, final FuncJsonObjectByte callBack) {handler.post(new Runnable() {@Overridepublic void run() {if (callBack != null) {callBack.onResponse(data);}}});}/*** 同步请求,不是很常用,因为会阻塞线程** @param url* @return*/public String syncGetByURL(String url) {//构建一个Request请求Request request = new Request.Builder().url(url).build();Response response = null;try {//同步请求数据response = client.newCall(request).execute();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {}return null;}/*** 请求指定的url,返回的结果是json字符串** @param url* @param callback*/public void syncJsonStringByURL(String url, final FuncJsonString callback) {final Request request = new Request.Builder().url(url).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.i(TAG, "解析失败");}//解析成功@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response != null && response.isSuccessful()) {onsuccessJsonStringMethod(response.body().string(), callback);}}});}/*** 返回字符串json的接口*/interface FuncJsonString {//处理我们返回的结果void onResponse(String result);}/*** 返回json对象的接口*/interface FuncJsonObject {//处理我们返回的结果void onResponse(JSONObject jsonObject);}/*** 返回json对象的接口*/interface FuncJsonObjectByte {//处理我们返回的结果void onResponse(byte[] result);}/*** 返回json对象的接口*/interface FuncJsonObjectBitmap {//处理我们返回的结果void onResponse(Bitmap bitmap);}}
这里可以看到,我们基本上没做什么东西,对吧,只是把常用的方法都复写作了一些简单的操作而已,而且我们的注释也写的十分详细,你需要扩展的话,直接扩展就好了,这样,我们去验证一下,xml中加上
<TextViewandroid:id="@+id/tv_json"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="json数据" />
<Buttonandroid:id="@+id/btn_json"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="解析json数据" />
好的,什么初始化的我就不写出来了,直接看点击事件
//解析jsonbtn_json.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//单例初始化OkHttpUtils okHttpUtils = OkHttpUtils.getInstance();/*** 地址* 成功回调*/okHttpUtils.syncJsonStringByURL(json_url, new OkHttpUtils.FuncJsonString() {@Overridepublic void onResponse(String result) {tv_json.setText(result);Log.i(TAG,""+result);}});}});
可以看到,是不是非常的简单就OK了。我们只要定义传url进入就可以了,而接口,我们使用的是豆瓣的接口
//json地址
private String json_url = "https://api.douban.com/v2/book/1220562";
这样我们可以看下运行结果
当然,我也是只提供一种思路罢了,这个封装类并不完善,还需要你自己根据需求来实施,好的,我这里也就继续来优化一下了
六.封装优化
前面可以看到,我们已经封装好了一个工具类,但是并不完善,现在呢,我们就完善的封装一下,当然,也只是针对功能点去优化,比如刚才我们只封装了一个解析返回json字符串,现在我们来一个解析直接返回一个json对象,嘿嘿,怎么做呢?
/*** 请求指定的url,返回的结果是json对象** @param url* @param callback*/public void syscJsonObjectByURL(String url, final FuncJsonObject callback) {final Request request = new Request.Builder().url(url).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.i(TAG, "解析失败");}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response != null && response.isSuccessful()) {onsuccessJsonObjectMethod(response.body().string(), callback);}}});}
跟之前的其实很类似,同样的,我们可以返回byte字节数组
/*** 请求指定的url,返回的结果是byte字节数组** @param url* @param callback*/public void syscGetByteByURL(String url, final FuncJsonObjectByte callback) {final Request request = new Request.Builder().url(url).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.i(TAG, "解析失败");}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response != null && response.isSuccessful()) {onsuccessJsonByteMethod(response.body().bytes(), callback);}}});}
我们也看到了,我们还剩下Bitmap,我们还自带裁剪功能哦,哈哈
/*** 请求指定的url,返回的结果是Bitmap* @param url* @param callback*/public void syscDownloadImageByURL(String url, final FuncJsonObjectBitmap callback){final Request request = new Request.Builder().url(url).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.i(TAG, "解析失败");}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response != null && response.isSuccessful()) {byte [] data = response.body().bytes();Bitmap bitmap = new TailorImageView().transform(BitmapFactory.decodeByteArray(data,0,data.length));callback.onResponse(bitmap);}}});}
到这里,基本的get封装就应该差不多写完了,但是别忘了,论post的重要性,既然如此,那我们就继续封装,首先实现的一个功能
post提交表单数据
开发中,也是有诸多需要post的地方的,毕竟安全性,传输都是个很不错的选择,我们继续写方法
/*** 向服务器提交表单** @param url 提交地址* @param params 提交数据* @param callback 提交回调*/public void sendDatafForClicent(String url, Map<String, String> params, final FuncJsonObject callback) {//表单对象,包含input开始的操作FormBody.Builder from = new FormBody.Builder();//键值对不为空,他的值也不为空if (params != null && !params.isEmpty()) {for (Map.Entry<String, String> entry : params.entrySet()) {//装载表单值from.add(entry.getKey(), entry.getValue());}}RequestBody body = from.build();//post提交Request request = new Request.Builder().url(url).post(body).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.i(TAG, "解析失败");}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response != null && response.isSuccessful()) {onsuccessJsonObjectMethod(response.body().string(), callback);}}});}
这里没有服务端,所以就不能测试了,我这里也就教大家怎么使用就好了,首先xml中定义一个按钮
<Buttonandroid:id="@+id/btn_post"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="POST表单提交" />
我们可以直接看他的点击事件
//post表单提交btn_post.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {OkHttpUtils okHttpUtils = OkHttpUtils.getInstance();//服务端的地址String post_url = "";//map集合HashMap<String, String> map = new HashMap<String, String>();map.put("username", "LGL");map.put("password", "12345678");okHttpUtils.sendDatafForClicent(post_url, map, new OkHttpUtils.FuncJsonObject() {@Overridepublic void onResponse(JSONObject jsonObject) {//输出结果Log.i(TAG, jsonObject.toString());}});}});
OK,这样就提交了表单,这就是一个完整的封装过程了,如果你问,那我们普通的请求怎么办呢?额,你看了这么久还不熟悉他的套路?我嘴角微微一笑,你的司机之路还很长啊,咳咳,跑题了,如果大家还有什么疑问的话,可以去鸿洋那里看看,我相信现在很多的文章都将了很多的基本使用的,所以我也不是想怎么去讲解析json什么的
- Android OkHttp完全解析 是时候来了解OkHttp了
2016/6/20补充:
Post提交数据,应该是这样判断的
if (params != null && !params.isEmpty())
有个!的判断,在Demo里面是没有的,现在及时改正了
本文的Demo我会上传到CSDN,大家可以下载
下载地址:http://download.csdn.net/detail/qq_26787115/9553992
如果大家对我有什么兴趣或者对我博客有兴趣,可以加群一起聊聊
通往Android的神奇之旅:555974449
OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据相关推荐
- OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据...
OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据 我们这片博文就来聊聊这个反响很不错的OkHttp了,标题是我恶搞的,本篇将着重详细的 ...
- 深聊性能测试,从入门到放弃之: Windows系统性能监控(二) 资源监控器介绍及使用。
资源监控器介绍及使用 1.引言 2.资源监视器 2.1 打开方式 2.2 基本介绍 2.3 使用 3.总结 1.引言 小屌丝:鱼哥,我看了你这篇<Windows系统性能监控(一) 性能监视器介绍 ...
- python自动登录并提交表单_用python模拟登录(解析cookie + 解析html + 表单提交 + 验证码识别 + excel读写 + 发送邮件)...
老婆大人每个月都要上一个网站上去查数据,然后做报表. 为了减轻老婆大人的工作压力,所以我决定做个小程序,减轻我老婆的工作量. 准备工作 1.tesseract-ocr 这个工具用来识别验证码,非常好用 ...
- Scott的ASP.net MVC框架系列文章之四:处理表单数据(2)
前几周我发表了一系列文章介绍我们正在研究的ASP.NET MVC框架.ASP.NET MVC框架为你提供了一种新的开发Web应用程序的途径,这种途径可以让应用程序变得更加层次清晰,而且更加有利于对代码 ...
- 小程序提交表单mysql_GitHub - kun19911227/minipro: 微信小程序提交带图片的表单
minipro 微信小程序提交带图片的表单 目录说明 upload_images ├── pages │ ├── upload_info 提交表单 │ └── display_info 信息展示 ├─ ...
- 微信提交表单到服务器,微信小程序页面表单如何跟图片一起上传服务器
拆开写. 表单提交是 wx.request 上传图片是 wx.uploadFile 你需要写一个通用图片上传接口,上传图片后台返回图片的url.这个通用接口在任何需要提交图片的表单都可以用到. 添加图 ...
- html把保留图片改为提交按钮,如何制作图片按钮,并为图片按钮添加提交表单和重置表单功能...
网页中有表单,表单的默认按钮样式不是很好看,很多人为了美观使用图片做按钮. 今天中国在 一.图片按钮的制作方法 1. 定义图像形式的提交按钮. 2.用CSS把图片设为按钮的背景 3.作用,设置其bac ...
- json数据解析_shell从入门到放弃解析json数据(2)
0x00 前言 json是程序猿经常遇到的数据格式,对于java,python对json的解析那是小菜一碟. 今天介绍一下shell里处理json的神器:jq 在这里先预设一个json数据,如下: j ...
- 入门到放弃node系列之网络模块(二)
为什么80%的码农都做不了架构师?>>> 前言 本文首发[一名打字员] 上一节我们刚刚介绍完node的HTTP和HTTPS模块,相信我们也对nodejs有了更深层次的理解,接下 ...
最新文章
- cocos2dx中关于Action动作的相关API的详细介绍
- 基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ
- Android开发之ADB常用命令
- 【全】.net core平台单元/集成测试结果、覆盖率、圈复杂度到可视化HTML报告之路...
- QT Core | 信号槽03 - 自定义信号与槽
- jQtouch 初体验
- centos操作系统版本获取
- Hadoop2.7.3伪分布式集群搭建
- 手机网站和PC网站兼容的响应式网页设计
- Layui中的table中toolbar自定义过程
- Windows10如何彻底卸载MySQL
- Ubuntu中EasyPR环境配置
- Beyond Compare 激活解决办法
- PHPWord 表格居中和合并单元格
- Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
- nodejs串口通信
- iptables 流量统计
- sqlserver2000安装时提示挂起并重启
- 精彩回顾 | Dev.Together 2022 开发者生态峰会圆满落幕
- 2.微处理器:8088功能结构图【BIU 和 EU】 + 8088【内部各寄存器】的解释