Wire协议缓冲器 一个人必须有一个代码! -奥马尔小 由于我们的团队和项目增长,数据的种类和数量也随之增加。 成功将您简单的数据模型转换为复杂的! 无论您的应用程序将数据存储到磁盘或网络传送信号,该数据的结构和解释应该是清楚的。 消费者最好的工作,
Wire协议缓冲器
“一个人必须有一个代码!” -奥马尔小
由于我们的团队和项目增长,数据的种类和数量也随之增加。成功将您简单的数据模型转换为复杂的!无论您的应用程序将数据存储到磁盘或网络传送信号,该数据的结构和解释应该是清楚的。消费者最好的工作,他们了解的数据!
架构描述和文档数据模型。如果你有数据,你应该有一个架构。
协议缓冲器
谷歌的协议缓冲器都围绕一个伟大的模式语言:
-
它的跨平台和语言无关。无论您使用的编程语言,你就可以使用原架构与应用程序。
-
原始模式是向后兼容的,面向未来的。作为您的应用程序失去旧的功能和获得新的可以发展你的架构。
-
它的重点。原架构描述你的数据模型。而已。
下面是一个示例消息定义:
syntax = "proto2";
package squareup.dinosaurs;
option java_package = "com.squareup.dinosaurs";
import "squareup/geology/period.proto";
message Dinosaur {
// Common name of this dinosaur, like "Stegosaurus".
optional string name = 1;
// URLs with images of this dinosaur.
repeated string picture_urls = 2;
optional squareup.geology.Period period = 5;
}
这里是一个枚举定义:
syntax = "proto2";
package squareup.geology;
option java_package = "com.squareup.geology";
enum Period {
// 145.5 million years ago — 66.0 million years ago.
CRETACEOUS = 1;
// 201.3 million years ago — 145.0 million years ago.
JURASSIC = 2;
// 252.17 million years ago — 201.3 million years ago.
TRIASSIC = 3;
}
这种模式语言是Protocol Buffers的'最大的特点。你甚至可以用它纯粹是为了文档的目的,如描述一个JSON API。
协议缓冲器还定义了符合模式的消息的紧凑二进制编码。这种编码快速编码,快速解码,小到传输,和小存储。二进制编码使用数字标签从架构,像5
的时间
以上。
例如,我们的编码这个恐龙:
{
name: "Stegosaurus",
period: JURASSIC
}
编码值仅仅是15个字节:
Hex Description
0a tag: name(1), field encoding: LENGTH_DELIMITED(2). 1 << 3 | 2
0b "Stegosaurus".length()
53 'S'
74 't'
65 'e'
67 'g'
6f 'o'
73 's'
61 'a'
75 'u'
72 'r'
75 'u'
73 's'
28 tag: period(5), field encoding: VARINT(0). 5 << 3 | 0
02 JURASSIC(2)
为什么网?
该协议缓冲器模式语言和二进制编码都是由谷歌定义。Wire是从广场的独立实现,它是专门针对Android和Java设计的。
对于在架构中定义的每个消息的类型,电线产生一个不可变模型类和它的建造者。生成的代码看起来像你手工编写代码:它的记录,格式化和简单。电线的API,应该感到在家里谁喜欢程序员有效的Java。
尽管如此,也有一些有趣的设计决策线:
-
电线消息宣布
公众最终
场,而不是通常的getter方法。这减少了生成的代码和代码执行。更少的代码是Android程序特别有利。 -
电线避免的情况下映射。声明为字段
picture_urls
在架构产生一个Java领域picture_urls
,而不是传统的pictureUrls
骆驼情况。虽然名字起初感到尴尬,它每次使用是梦幻般的grep
或更复杂的搜索工具。,Java源代码和数据模式之间航行时没有更多的映射。它还提供了一个善意提醒调用代码,原消息是有点特殊。 -
基本类型总是装箱。如果字段不存在,它的价值是
零
。这是用于自然可选字段,如恐龙,其周期是未知的。字段也可以为空,由于模式演变:如果明天我们添加一个食肉动物
布尔给我们的消息定义,今天的数据不会有该字段的值。
下面是在紧凑型生成的代码恐龙
上述定义的消息:
通过Wire协议缓冲编译器生成的代码//,不编辑。
//源文件:squareup /恐龙/ dinosaur.proto在9:1
package com.squareup.dinosaurs;
import com.squareup.geology.Period;
import com.squareup.wire.Message;
import com.squareup.wire.ProtoAdapter;
import com.squareup.wire.WireField;
import java.util.List;
import okio.ByteString;
public final class Dinosaur extends Message<Dinosaur, Dinosaur.Builder> {
public static final ProtoAdapter<Dinosaur> ADAPTER = ProtoAdapter.newMessageAdapter(Dinosaur.class);
private static final long serialVersionUID = 0L;
public static final String DEFAULT_NAME = "";
public static final Period DEFAULT_PERIOD = Period.CRETACEOUS;
/**
* Common name of this dinosaur, like "Stegosaurus".
*/
@WireField(
tag = 1,
adapter = "com.squareup.wire.ProtoAdapter#STRING"
)
public final String name;
/**
* URLs with images of this dinosaur.
*/
@WireField(
tag = 2,
adapter = "com.squareup.wire.ProtoAdapter#STRING",
label = WireField.Label.REPEATED
)
public final List<String> picture_urls;
@WireField(
tag = 5,
adapter = "com.squareup.geology.Period#ADAPTER"
)
public final Period period;
public Dinosaur(String name, List<String> picture_urls, Period period) {
this(name, picture_urls, period, ByteString.EMPTY);
}
public Dinosaur(String name, List<String> picture_urls, Period period, ByteString unknownFields) {
super(unknownFields);
this.name = name;
this.picture_urls = immutableCopyOf("picture_urls", picture_urls);
this.period = period;
}
@Override
public Builder newBuilder() {
Builder builder = new Builder();
builder.name = name;
builder.picture_urls = copyOf("picture_urls", picture_urls);
builder.period = period;
builder.addUnknownFields(unknownFields());
return builder;
}
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof Dinosaur)) return false;
Dinosaur o = (Dinosaur) other;
return equals(unknownFields(), o.unknownFields())
&& equals(name, o.name)
&& equals(picture_urls, o.picture_urls)
&& equals(period, o.period);
}
@Override
public int hashCode() {
int result = super.hashCode;
if (result == 0) {
result = unknownFields().hashCode();
result = result * 37 + (name != null ? name.hashCode() : 0);
result = result * 37 + (picture_urls != null ? picture_urls.hashCode() : 1);
result = result * 37 + (period != null ? period.hashCode() : 0);
super.hashCode = result;
}
return result;
}
public static final class Builder extends