Android基础(15)—网络传输协议

网络传输协议

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模式架构

精彩内容不够看?更多精彩内容,请到微信搜索 “危君子频道” 订阅号,每周更新,欢迎大家关注订阅!

微信公众号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342