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 com.squareup.wire.Message.Builder<Dinosaur, Builder> {
public String name; public List<String> picture_urls; public Period period; public Builder() {
picture_urls = newMutableList();
} /**
* Common name of this dinosaur, like "Stegosaurus".
*/
public Builder name(String name) {
this.name = name;
return this;
} /**
* URLs with images of this dinosaur.
*/
public Builder picture_urls(List<String> picture_urls) {
checkElementsNotNull(picture_urls);
this.picture_urls = picture_urls;
return this;
} public Builder period(Period period) {
this.period = period;
return this;
} @Override
public Dinosaur build() {
return new Dinosaur(name, picture_urls, period, buildUnknownFields());
}
}
}

在Java代码来创建和访问原车型是紧凑和可读性:


Dinosaur stegosaurus = new Dinosaur.Builder()
.name("Stegosaurus")
.period(Period.JURASSIC)
.build(); System.out.println("My favorite dinosaur existed in the " + stegosaurus.period + " period.");

每种类型都有一个对应ProtoAdapter能够编码一个信息字节和解码字节回一个消息。


Dinosaur stegosaurus = ...
byte[] stegosaurusBytes = Dinosaur.ADAPTER.encode(stegosaurus); byte[] tyrannosaurusBytes = ...
Dinosaur tyrannosaurus = Dinosaur.ADAPTER.decode(tyrannosaurusBytes);

当访问一个字段,使用Wire.get()与相应的默认更换空值:


Period period = Wire.get(stegosaurus.period, Dinosaur.DEFAULT_PERIOD);

这相当于如下:


Period period = stegosaurus.period != null ? stegosaurus.period : Dinosaur.DEFAULT_PERIOD;

生成代码带线

资讯的编译器通过一个Maven插件可用。把.proto在项目的源代码 的src / main /原目录中,然后用插件生成的.java文件。该插件将生成的Java代码会自动添加到项目的源根。


<build>
<plugins>
<plugin>
<groupId>com.squareup.wire</groupId>
<artifactId>wire-maven-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate-sources</goal>
</goals>
<configuration>
<protoFiles>
<param>squareup/dinosaurs/dinosaur.proto</param>
<param>squareup/geology/period.proto</param>
</protoFiles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

导线可以读取.proto从本地文件系统,并从内的文件的.jar文件。

编译器可以随意删改模式根类型及其传递依赖的一个子集。Java服务和Android应用程序可以使用每一个更大的共享模式的子集:共享模式时,项目之间,这很有用。

如果你不使用Maven,编译器也有一个命令行界面。刚刚替补 丝编译器版本-JAR与- dependencies.jar同的路径罐子。


% java -jar wire-compiler-VERSION-jar-with-dependencies.jar \
--proto_path=src/main/proto \
--java_out=out \
squareup/dinosaurs/dinosaur.proto \
squareup/geology/period.proto
Writing com.squareup.dinosaurs.Dinosaur to out
Writing com.squareup.geology.Period to out

如果你使用Proguard的,那么你需要添加规则。最简单的方法是,告诉Proguard的不要碰线运行时库和产生的协议缓冲区(当然这些简单的规则将错过机会缩小和优化的代码):


-keep class com.squareup.wire.** { *; }
-keep class com.yourcompany.yourgeneratedcode.** { *; }

获得线

线运行包中包含了必须包含在使用线生成的代码的应用程序的运行时支持库。

使用Maven:


<dependency>
<groupId>com.squareup.wire</groupId>
<artifactId>wire-runtime</artifactId>
<version>2.1.1</version>
</dependency>

Android和Java的轻巧Wire协议缓冲器的更多相关文章

  1. 移动开发首页业界资讯移动应用平台技术专题 输入您要搜索的内容 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)

    在阅读本文前需要对socket以及自定义协议有一个基本的了解,可以先查看上一篇文章<基于Java Socket的自定义协议,实现Android与服务器的长连接(一)>学习相关的基础知识点. ...

  2. Android(java)学习笔记80:UDP协议发送数据

    UDP协议发送数据:我们总是先运行接收端,再运行发送端发送端: 1 package cn.itcast_02; import java.io.IOException; import java.net. ...

  3. Android(java)学习笔记20:UDP协议发送数据

    1. UDP协议发送数据:我们总是先运行接收端,再运行发送端发送端: package cn.itcast_02; import java.io.IOException; import java.net ...

  4. Android(java)学习笔记201:网络图片浏览器的实现(ANR)

    1.我们在Android下,实现使用http协议进行网络通信,请求网络数据.这里是获取网络上的图片信息,让它可以显示在手机上: 但是我们这个手机连接网络是很费时间,如果我们在主线程(UI线程)中写这个 ...

  5. Android(java)学习笔记213:开源框架post和get方式提交数据(qq登录案例)

    1.前面提到Http的get/post方式  . HttpClient方式,实际工作的时候不常用到,因为这些方式编写代码是很麻烦的 2.Android应用会经常使用http协议进行传输,网上会有很完善 ...

  6. Android(java)学习笔记205:网易新闻RSS客户端应用编写逻辑过程

    1.我们的项目需求是编写一个新闻RSS浏览器,RSS(Really Simple Syndication)是一种描述和同步网站内容的格式,是使用最广泛的XML应用.RSS目前广泛用于网上新闻频道,bl ...

  7. Android(java)学习笔记257:JNI之helloword案例(利用NDK工具)

    1.逻辑思路过程图: 2.下面通过一个HelloWorld案例来说明一下JNI利用NDK开发过程(步骤) 分析:我们在Win7系统下编译的C语言代码,我们知道C语言依赖操作系统,不能跨平台,所以我们要 ...

  8. Android(java)学习笔记148:网易新闻RSS客户端应用编写逻辑过程

    1.我们的项目需求是编写一个新闻RSS浏览器,RSS(Really Simple Syndication)是一种描述和同步网站内容的格式,是使用最广泛的XML应用.RSS目前广泛用于网上新闻频道,bl ...

  9. Android(java)学习笔记144:网络图片浏览器的实现(ANR)

    1.我们在Android下,实现使用http协议进行网络通信,请求网络数据.这里是获取网络上的图片信息,让它可以显示在手机上: 但是我们这个手机连接网络是很费时间,如果我们在主线程(UI线程)中写这个 ...

随机推荐

  1. FORM - 实现某数据项自动按记录序号加一操作

    ---- 设块名为VO,要操作的数据项为VO_ID,在该块中建立块级触发子WHEN-CREATE- RECORD,每当生成新记录时VO_ID就会自动加一了,加入如下代码: :VO_ID:=:Syste ...

  2. Android开发之BroadcastReceiver的使用

    1.静态注册. 在manifest中注册. <receiver android:name="com.exce.learnbroadcastreceiver.MyReceiver&quo ...

  3. Java实现人民币大写精讲

    想要实现人民币大写,在发票等场景中使用?? 1234.56显示为:壹仟贰佰叁拾肆元伍角陆分,那就往下看看吧! 本程序可以实现 0 到 9999 9999 9999.994 以内的人民币大写转换,精确到 ...

  4. c语言时间库函数#include<time.h>

    日期与时间函数<time.h> 头文件<time.h>中说明了一些用于处理日期和时间的类型和函数.其中的一部分函数用于处理当地时间,因为时区等原因,当地时间与日历时间可能不相同 ...

  5. CDOJ 1071 秋实大哥下棋 线段树

    分析:运用扫描线,先从左到右扫描,用纵坐标进行建树, 随着扫描线的右向右移动.不断更新横坐标小于扫描线的车 更新的时候  在树中更新车的纵坐标的位置,把该位置的值变成该车的横坐标 线段树维护的是区间最 ...

  6. 快速定位隐蔽的sql性能问题及调优【转载】

    在前几天,有个开发同事问我一个问题,其实也算是技术救援,他说在有个job数据处理的频率比较高,在测试环境中很难定位出在哪有问题,而且速度也还能接 受,但是在生产环境中总是会慢一些,希望我能在测试环境中 ...

  7. 洛谷P1117 棋盘游戏

    洛谷1117 棋盘游戏 题目描述 在一个4*4的棋盘上有8个黑棋和8个白棋,当且仅当两个格子有公共边,这两个格子上的棋是相邻的.移动棋子的规则是交换相邻两个棋子.现在给出一个初始棋盘和一个最终棋盘,要 ...

  8. codeforces629C Famil Door and Brackets (dp)

    题意:给你一个长度为n的括号匹配串(不一定恰好匹配),让你在这个串的前面加p串和后面加上q串,使得这个括号串平衡(平衡的含义是对于任意位置的括号前缀和大于等于0,且最后的前缀和为0). 思路:枚举这个 ...

  9. POJ2299: Ultra-QuickSort-合并排序解决逆序数问题

    #include<iostream> #include<malloc.h> using namespace std; long long ans; void merge(int ...

  10. 【ACM/ICPC2013】树形动态规划专题

    前言:按照计划,昨天应该是完成树形DP7题和二分图.最大流基础专题,但是由于我智商实在拙计,一直在理解树形DP的思想,所以第二个专题只能顺延到今天了.但是昨天把树形DP弄了个5成懂我是很高兴的!下面我 ...