网络传输协议
App与服务器交互就会涉及到信息的交换,而信息的交互就必然需要一套完整的数据协议。网络传输协议或简称为传送协议(Communications Protocol),是指计算机通信的共同语言。现在最普及的计算机通信为网络通信,所以“传输协议”一般都指计算机通信的传输协议,如TCP/IP、NetBEUI等。然而,传输协议也存在于计算机的其他形式通信,例如,面向对象编程里面对象之间的通信;操作系统内不同程序之间的消息,都需要有一个传输协议,以确保传信双方能够沟通无间。
简单而言网络传输协议就是App端与服务器端交互的时候约定好的内容格式。比如我们常见的Json格式,xml格式等,这些都是网络传输协议,而现在在App开发中比较常见的网络传输协议有三种:XML、JSON、PB
XML
介绍
XML是一种最早的网络传输协议,常见于java web开发中,不单单作为网络层的参数协议,还常见于各种配置文件中,在移动开发中也常见但是已不是主流的网络传输协议。
优点
可读性强、解析方便
缺点
效率不高、资源消耗过大
解析方式:
DOM解析
操作
解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。
优点
整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能。
缺点
将整个文档调入内存(包括无用的节点),浪费时间和空间;
使用场合
一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)
SAX解析
操作
SAX ,事件驱动型解析方式。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。
优点
不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。
缺点
不是持久的:事件过后,若没保存数据,那么数据就丢了;无状态性:从事件中只能得到文本,但不知该文本属于哪个元素。
使用场合
Applet;只需XML文档的少量内容,很少回头访问;机器内存少。
PULL解析
PULL解析方式是Android专门为移动设备上解析XML文件而设计的一种解析方式,显而易见的其更加适用于移动设备解析XML文件。PULL解析和SAX解析很相似,PULL解析和SAX解析不一样的地方是PULL读取XML文件后触发相应的事件调用方法返回的是数字,还有PULL可以在程序中控制想解析到哪里就可以停止解析。
JSON
介绍
JSON是在移动端比较常见的网络传输协议,它较XML格式更加的简单和“小”,因此比XML更适合移动端对流量和内存的控制。
优点
较XML格式更加小巧。
缺点
传输效率也不是特别高,但相较于xml提高了很多。
解析方式
Gson解析
Gson解析方式是Google开源的一套解析方式,通过提供的Gson jar包,通过静态方法直接由字符串解析成java对象,简单方便。
1.用Gson的jar包导入到项目libs目录下,或直接通过Gradle添加依赖:
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
}
2.创建Gson对象:
Gson gson = new Gson();
3.通过创建的Gson对象调用fromJson()方法,返回该json数据对象的Java对象:
ShopInfo shopInfo = gson.fromJson(json, ShopInfo.class);
注意要记得创建对象的JavaBean类;要求json对象中的key的名称与Java对象的JavaBean类中的属性名要相同,否则解析不成功!
原生技术解析
JSONObject在org.json下面的包中,其也是一个解析Json字符串的工具类
特点:很麻烦,对于复杂的json数据解析很容易出错!(不推荐使用)
解析JSON对象的API:JSONObject
1.获取或创建JSON数据(为了方便,这里就直接创建了):
String json = "{\n" +
"\t\"id\":2, \"name\":\"金鱼\", \n" +
"\t\"price\":12.3, \n" + "\t\"imagePath\":\"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544507386520&di=1942ac3c18b58a5e610d1f14f12a43f9&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimage%2Fc0%253Dshijue1%252C0%252C0%252C294%252C40%2Fsign%3D6fafa452dc88d43fe4a499b11577b86e%2F8694a4c27d1ed21b9d582dc2a76eddc451da3f07.jpg\"\n" +
"}\n";
ShopInfo shopInfo = null;
2.解析Json对象:
try { //需要做try_catch异常处理
JSONObject jsonObject = new JSONObject(json);
int id1 = jsonObject.optInt("id");
String name = jsonObject.optString("name");
double price = jsonObject.optDouble("price");
String imagePath = jsonObject.optString("imagePath");
// 封装Java对象
shopInfo = new ShopInfo(id1, name, price, imagePath);
} catch (JSONException e) {
e.printStackTrace();
}
3.创建JavaBean类,并显示解析后的数据:
tv_native_last.setText(shopInfo.toString());
解析JSON数组的API:JSONArray
1.获取或创建JSON数据:
String json = "[\n" +
" {\n" +
" \"id\": 1,\n" +
" \"imagePath\": \"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544507386520&di=1942ac3c18b58a5e610d1f14f12a43f9&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimage%2Fc0%253Dshijue1%252C0%252C0%252C294%252C40%2Fsign%3D6fafa452dc88d43fe4a499b11577b86e%2F8694a4c27d1ed21b9d582dc2a76eddc451da3f07.jpg\",\n" +
" \"name\": \"金鱼1\",\n" +
" \"price\": 12.3\n" +
" },\n" +
" {\n" +
" \"id\": 2,\n" +
" \"imagePath\": \"https://tgi13.jia.com/114/937/14937808.jpg\",\n" +
" \"name\": \"金鱼2\",\n" +
" \"price\": 12.5\n" +
" }\n" +
"]";
2.解析JSON数组:
try {
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
if (jsonObject != null) {
int id = jsonObject.optInt("id");
String name = jsonObject.optString("name");
double price = jsonObject.optDouble("price");
String imagePath = jsonObject.optString("imagePath");
// 封装Java对象
ShopInfo shopInfo = new ShopInfo(id, name, price, imagePath);
shops.add(shopInfo);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
3.显示解析后的数据:
tv_native_last.setText(shops.toString());
FastJson解析
FastJson是阿里巴巴开源的一个解析Json数据的类库,能够将json字符串解析成java对象。它采用了一种“假定有序、快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。
1.用FastJson解析对象:
利用Fastjson的JSON调用parseObject()方法,获取转换后的Java对象。
注意要记得创建对象的JavaBean类;要求json对象中的key的名称与Java对象的JavaBean类中的属性名要相同,否则解析不成功!
// 1 获取或创建json数据
String json = "{\n" +
"\t\"id\":2, \"name\":\"金鱼\", \n" +
"\t\"price\":12.3, \n" +
"\t\"imagePath\":\"https://tgi13.jia.com/114/937/14937808.jpg\"\n" +"}\n";
// 2 解析JSON数据
ShopInfo shopInfo = JSON.parseObject(json, ShopInfo.class);
// 3 显示数据
tv_fastjson_last.setText(shopInfo.toString());
2.用FastJson解析数组:
利用Fastjson的JSON调用parseArray()方法,获取转换后的Java集合。
//1.获取或创建json数据
String json = "[\n" +
" {\n" +
" \"id\": 1,\n" +
" \"imagePath\": \"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544507386520&di=1942ac3c18b58a5e610d1f14f12a43f9&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimage%2Fc0%253Dshijue1%252C0%252C0%252C294%252C40%2Fsign%3D6fafa452dc88d43fe4a499b11577b86e%2F8694a4c27d1ed21b9d582dc2a76eddc451da3f07.jpg\",\n" +
" \"name\": \"金鱼1\",\n" +
" \"price\": 12.3\n" +
" },\n" +
" {\n" +
" \"id\": 2,\n" +
" \"imagePath\": \"https://tgi13.jia.com/114/937/14937808.jpg\",\n" +
" \"name\": \"金鱼2\",\n" +
" \"price\": 12.5\n" +
" }\n" +
"]";
//2.解析json数据
List<ShopInfo shopInfos = JSON.parseArray(json,ShopInfo.class);
//3.显示数据
tv_fastjson_last.setText(shopInfos.toString());
ProtocolBuffer
介绍
ProtocolBuffer(PB) 是一种轻便高效的结构化数据存储格式,可以用于结构化数据的序列化,是Google开源的一套二进制流网络传输协议,它独立于语言,独立于平台。类似XML和JSON,但PB比前两者更高效和省空间,在移动开发中更为用户省流量。从编码方式来看,PB采用Zigzag编码并充分利用Varint技术,从而实现二进制级的空间节省。
优点
传输效率快(比XML和JSON快10-20倍),文档型协议。
缺点
使用不太方便:XML和JSON一般在使用的时候都需要保存一份说明文档和一个实际的java类,而ProtocolBuffer在使用的时候其定义的格式就是说明文档,简单明了而且可以将其编译成各个平台的类库,以java平台为例,其编程成jar之后,若定义文件发生了变化,则再使用jar包的话就会报错,必须重新编译,这也就保证了App端与服务器端的协议统一性。
解析步骤
1.定义ProtoBuf文件并存为addressbook.proto
option java_package = "com.example.jimyoungwei";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
在protobuf中定义了三种修饰符,分别为:required,optional,repeated。其中:
Required:表示的是这个字段必须要传递,不可为空;
Optional:表示的是这个字段可传可不传,可以为空;
Repeated:表示这个字段传递的是列表数据
2.将proto文件编译成 jar 包
a、下载安装编译器
b、找到.proto文件位置
c、运行编译器,指定源目录和目标目录,定位.proto文件到源目录,然后执行:
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto
protoc -I=. --java_out=. addressbook.proto
3.在Android代码中使用
a、加入类库jar包
b、加入刚生产成的实体类的文件
(1)实体转字节
String imei = getImei();
ObdRightBean.ObdRightRequest obdRightRequest;
obdRightRequest =
ObdRightBean.ObdRightRequest.newBuilder().setImei(imei).build();
//转换成字节
obdRightRequest.toByteArray()
(2)字节转实体
ObdRightBean.ObdRightResponse obdProductResponse = null;
obdProductResponse =
ObdRightBean.ObdRightResponse.parseFrom(bytes2);
int code = obdProductResponse.getCode();
小结
对比 | XML | JSON | PB(protocol buffer) |
---|---|---|---|
数据保存方式 | 文本 | 文本 | 二进制 |
可读性 | 较好 | 较好 | 不可读 |
解析效率 | 慢 | 一般 | 快 |
语言支持 | 所有语言 | 所有语言 | C++/Java/Python等(由google提供) |
适用范围 | 文件存储、数据交互 | 文件存储、数据交互 | 文件存储、数据交互 |
上一篇:Android基础(14)—常用第三方库 EventBus
下一篇:Android基础(16)—MVP模式架构
精彩内容不够看?更多精彩内容,请到微信搜索 “危君子频道” 订阅号,每周更新,欢迎大家关注订阅!