美文网首页简友广场
Android基础(15)—网络传输协议

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

作者: 危君子频道 | 来源:发表于2020-06-23 17:28 被阅读0次

    网络传输协议

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

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

    微信公众号

    相关文章

      网友评论

        本文标题:Android基础(15)—网络传输协议

        本文链接:https://www.haomeiwen.com/subject/qvbutktx.html