Protobuf在Android上面的应用

作者: 一叶知秋yi | 来源:发表于2018-10-21 22:10 被阅读20次

    背景

    平时移动端和端之间的数据传输基本都是用的json或者xml,对于Protobuf之前一直有听说过,相比于json和xml有诸多好处,例如数据量小,序列化和反序列化速度快等,所以我们也来尝试一下Protobuf。

    Quick Start

    在系统的根目录的build.gradle中添加插件

    dependencies {
            classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.2'
    }
    
    • 踩坑tips
      这里有个坑,AndroidStudio3.0以上一定要采用0.8.2及以上的版本,否则编译阶段会报错

    接下来是模块中的build.gradle的配置,首先添加插件

    apply plugin: 'com.google.protobuf'
    

    然后添加配置

    android {
      protobuf {
            protoc {
                artifact = 'com.google.protobuf:protoc:3.0.0'
            }
            plugins {
                javalite {
                    artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
                }
            }
    
            generateProtoTasks {
                all().each { task ->
                    task.builtins {
                        remove java
                    }
                    task.builtins {
                        java { }
                        cpp { }
                    }
                }
            }
        }
    }
    

    还有一个代码目录的配置

    sourceSets {
            main {
                java {
                    srcDir 'src/main/java'
                }
                proto {
                    srcDir 'src/main/proto'
                }
            }
        }
    

    我们的.proto文件就放在这个目录下就好了
    最后添加依赖

    compile 'com.google.protobuf:protobuf-java:3.5.1'
    
    • 踩坑tips
      这里也有个很有意思的问题,之前我用的是protobuf-lite版本
      compile "com.google.protobuf:protobuf-lite:3.0.0"
      然而当我使用的时候发现找不到proto实例转化为字节流的方法toByteArray()等方法,google了一下,也有不少人遇到同样的问题。最后通过这个问题的答案中找到灵感 protobuf找不到toByteArray()方法 应该是依赖有问题,然后就到了还是不要用精简版,最后问题解决。

    至此,protobuf的运行环境已经完全搭建好了。网上有一些文章讲的是自己编译protobuf然后进行依赖,这种方式当然也可以,读者有兴趣的可以自行尝试。

    Demo

    那么该如何写呢,我们先来个最简单的Pojo类的例子。在上面定义好的proto目录下面创建一个.proto文件,内容如下

    syntax = "proto3";
      option java_package = "com.xxx.xxx";
      option java_outer_classname = "BaseProto";
    
    message Person {
        string name = 1;
        int32 id = 2;
        string email = 3;
        string phone = 4;
    }
    

    看起来还是比较容易理解的,如果上面环境搭建没有问题的话,同步一下项目之后,我们就会生成这个Person类了,下面以一个最简单的序列化和反序列化过程来说明一下这个类的使用方法

           try {
                BaseProto.Person.Builder builder = BaseProto.Person.newBuilder();
                builder.setEmail("xxxxx@qq.com");
                builder.setName("xx");
                builder.setId(1);
                builder.setPhone("13xxxxxxxxx");
    
                File file = new File(Environment.getExternalStorageDirectory() + 
                                     File.separator + "proto_persion");
                if(!file.exists()) {
                    file.createNewFile();
                }
                //序列化
                FileOutputStream outputStream = new FileOutputStream(file);
                builder.build().writeTo(outputStream);
               
                //反序列化
                InputStream inputStream = new FileInputStream(file);
                BaseProto.Person person1 = BaseProto.Person.parseFrom(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
    

    BaseProto就是上面.proto中定义的java_outer_classnamePerson类通过构建者模式来完成实例化,可以通过writeTo(OutputStream output)方法来讲字节流写入到对应的文件,然后通过parseFrom即可完成反序列化,总得来说,用起来还是比较方便的。

    后记

    protobuf从一个google内部使用的工具,发展到今天,肯定还是有其可取的优点的。只不过现在泛用性肯定还是比不上json和xml,不过作为一个项目可优化的点,学习一下还是可以的。

    相关文章

      网友评论

        本文标题:Protobuf在Android上面的应用

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