Android      Android中使用protobuf,谷歌的Protocol Buffers简单入门   
文章目录  [隐藏]

Android中使用protobuf
Protocol Buffers


Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。同XML相比,Protocol buffers在序列化结构化数据方面有许多优点(google官方提出):
• 更简单
• 数据描述文件只需原来的1/10至1/3
• 解析速度是原来的20倍至100倍
• 减少了二义性
• 生成了更容易在编程中使用的数据访问类
08年7月8号将其作为开源项目对外公布。


官方主页地址:https://developers.google.cn/protocol-buffers/
官方开源地址:https://github.com/google/protobuf
相关jar的maven:http://mvnrepository.com/artifact/com.google.protobuf

一.protobuf-java-[version].jar和protoc.exe

http://central.maven.org/maven2/com/google/protobuf/protobuf-java/3.1.0/protobuf-java-3.1.0.jar
https://github.com/google/protobuf/releases/download/v3.1.0/protoc-3.1.0-win32.zip\bin\protoc.exe
注意,本文使用的是3.x 。


使用maven打包protobuf的jar(http://www.cnblogs.com/superbi/p/4368240.html)
0.安装并配置好JDK,安装并配置好maven。
1.从github下载并解压protobuf-xx.xx.xx.zip,并把protoc-xx.xx.xx-win32.zip中的proto.exe放到protobuf-xx.xx.xx.zip解压文件夹中的src目录,如(D:\protobuf-2.6.1\src)
2.打开cmd,并进入protobuf的解压中的java目录,如(D:\protobuf-2.6.1\java),运行mvn package或者mvn install,运行此命令需要internet(联网)的支持
3.编译停止后在cmd窗口中看到build success时,恭喜你,jar生成了,jar文件在protobuf下java中的target目录,如(D:\protobuf-2.6.1\java\target)

二.定义数据结构

首先同java类,创建Persion.proto文件(建议文件名和代码中message标识的类名不一样)。

2.x版本代码:


3.x版本代码:

syntax = "proto3"一句是转换为java代码时的建议设置,不指定会给出警告。
如果syntax = "proto2",修饰符要显示的指定,否则别指定。
“message”如果java的关键字“class”。“Persion”就同java中的类名。大括号内就和声明一个javabean一样了。


修饰符原文说明:
https://developers.google.cn/protocol-buffers/docs/javatutorial
• required: a value for the field must be provided, otherwise the message will be considered "uninitialized". Trying to build an uninitialized message will throw a RuntimeException. Parsing an uninitialized message will throw an IOException. Other than this, a required field behaves exactly like an optional field.
• optional: the field may or may not be set. If an optional field value isn't set, a default value is used. For simple types, you can specify your own default value, as we've done for the phone number type in the example. Otherwise, a system default is used: zero for numeric types, the empty string for strings, false for bools. For embedded messages, the default value is always the "default instance" or "prototype" of the message, which has none of its fields set. Calling the accessor to get the value of an optional (or required) field which has not been explicitly set always returns that field's default value.
• repeated: the field may be repeated any number of times (including zero). The order of the repeated values will be preserved in the protocol buffer. Think of repeated fields as dynamically sized arrays.
• Required Is Forever You should be very careful about marking fields as required. If at some point you wish to stop writing or sending a required field, it will be problematic to change the field to an optional field – old readers will consider messages without this field to be incomplete and may reject or drop them unintentionally. You should consider writing application-specific custom validation routines for your buffers instead. Some engineers at Google have come to the conclusion that using required does more harm than good; they prefer to use only optional and repeated. However, this view is not universal.


数据类型原文说明:
https://developers.google.cn/protocol-buffers/docs/proto3#scalar

属性的默认值:
https://developers.google.cn/protocol-buffers/docs/proto3#default
• For strings, the default value is the empty string.
• For bytes, the default value is empty bytes.
• For bools, the default value is false.
• For numeric types, the default value is zero.
• For enums, the default value is the first defined enum value, which must be 0.
• For message fields, the field is not set. Its exact value is language-dependent. See the generated code guide for details.
对于字符串,默认值为空字符串。
对于字节,默认值为空字节。
对于bools,默认值为false。
对于数字类型,默认值为零。
对于枚举,默认值为第一个定义的枚举值,它必须为0。
对于消息字段,未设置字段。 它的确切值是语言相关的。 有关详细信息,请参阅生成的代码指南。

常用配置

1)包和类名

Person1.proto文件


2)属性的嵌套

Person2.proto文件

3)引用

Person3.proto文件


三.生成Java类

通用代码

使用前面准备好的protoc.exe,在cmd命令行运行:
protoc.exe --java_out=输出目录 源文件


指定了包和类名的Persion1.proto文件生成的java类:

嵌套属性的Persion2.proto文件生成的java类:

引用其他proto的Persion3.proto文件生成的java类:

针对Android生成代码

http://www.jianshu.com/p/185fc0e13028

编译选项,选项之间用逗号隔开(大括号中的为可选值):
• optional_field_style={default, accessors, reftypes},定义每个字段所生成的代码的格式:
• default:proto中每个字段生成一个public的可变的值;
• accessors:proto中每个optional字段会封装成一个private的值和4个用于操作该值的方法,分别是get(), set(), has()和clear(),在accessors选项中,required字段依旧是生成public的可变的值,repeated字段依旧是生成一个array;
要注意的是,当启用accessors选项时,使用Proguard混淆时,一定禁用-dontoptimize选项和启用-allowaccessmodification选项,这能够在项目编译时去掉那些没被调用的方法,减少最终的代码量;
• reftypes:proto中每个字段都会生成一个public的可变的值,与default不同的是,对于每个基本数据类型,如int,float等,都会使用Java对应的内建类型,并初始化为null(比如int会使用Java.lang.Integer类来替代),这样会带来额外的开销,好处是你可以避免歧义,比如optional int的字段,收到为0的值时,会分不清到底传来的值是0,还是这个字段为空
• enum_style={c, java} (default: c),定义枚举的格式,使用java style。
• ignore_services={true,false} (default: false),Protobuf Nano不支持services,如果在proto文件中定义了services,会导致编译错误,将该选项置为true,在编译时会忽略services相关的内容。
• parcelable_messages={true,false} (default: false),这个选项很重要,在android中,Parcelable是序列化对象的接口,很多数据交换都要应用到这个接口,比如Intent,和进程间通信。开启该选项,Protobuf Nano所生成的Java对象都会自动实现Parcelable接口,Intent和进程间通信就能直接使用这些对象。


可以将生成的java文件放到理想包里,然后将文件代码的package改为实际的包。
建议将parcelable_messages设为false,因为3.1.0版的nano jar中没有提供此类。也许是3.x版本比2.x牛逼很多,已经不需要通过ParcelableMessageNano类进行序列化。

四.在Android中使用

1.protobuf-javanano

http://central.maven.org/maven2/com/google/protobuf/nano/protobuf-javanano/3.1.0/protobuf-javanano-3.1.0.jar

•在MyEclipse和Android Studio中引入protobuf。
方式1,使用上面链接给出的jar。
方式2,AS通过gradle引入:

•将之前生成的Persion.java或Person.java引入。这里先引入Person.java瞧瞧安卓版本的用法。


1)服务端


首先定义一个Servlet,

然后将Servlet注册到web.xml。最后其它服务。


2)App端


网络请求使用post方式,

数据的封装发送,

2.protobuf-java

proto文件。从上面也看得出,message关键字声明的类名“SuperPerson”是最终java文件里实际使用的内部类,设计这个类、类名很关键。

生成java类。

将生成的java文件放入安卓项目和服务端项目中,替换上面的nano版。

安卓中的引用。

服务端解析代码没有变化,注意替换Person文件和jar包即可。

App端代码有变化,数据对象使用Builder进行创建。






可前往此处下载 链接:http://pan.baidu.com/s/1o8O2plw 密码:idby

承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设