Protobuf3使用总结

集成protobuf

root build.gradle

buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
    }
    dependencies {      
       classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.13"
    }
}	

app build.gradle

apply plugin: 'com.google.protobuf'

android {

    sourceSets {
        main {
            java {
                srcDir 'src/main/java'
            }
            proto {
                srcDir 'src/main/proto'
                include '**/*.proto'
            }
        }
    }

}

dependencies {
    implementation "com.google.protobuf:protobuf-javalite:4.0.0-rc-2"
}

protobuf {
    protoc {
        artifact = ""com.google.protobuf:protoc:4.0.0-rc-2"
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option "lite"
                }
            }
        }
    }
}

集成wire

  1. root build.gradle

    buildscript{
      repositories{
        google()
        jcenter()
        mavenCentral()
      }
    	dependencies{
    		classpath "com.squareup.wire:wire-gradle-plugin:3.3.0"
    	}
    }
    
  2. app build.gradle

    apply plugin: 'com.squareup.wire'
    
    android{
      ...
         sourceSets {
            main.java.srcDirs += "$buildDir/generated/source/wire"
        }
      ...
    }
    
    dependencies{
      implementation "com.squareup.wire:wire-runtime:3.3.0"
    }
    
    wire{
      kotlin{
        android = true
      }
    }
    
    ktlint {
       ...
        filter {
            exclude { projectDir.toURI().relativize(it.file.toURI()).path.contains("/generated/") }
        }
      ...
    }
    

创建protobuf

先来看一下样例:

//设置protobuf的版本,当前最新的是proto3
syntax = "proto3";

//设置proto文件的命名空间
package Haley.Common;

//引入其他的proto文件(Java不支持)
//import "google/protobuf/any.proto";

//设置proto生成代码后的命令空间,AS编译默认会在/build/generated/source/proto/目录下生成java或kotlin的类文件
option java_package = "com.haley.test.data";

//这个名字不能与下文的message名字冲突,Person已经是一个message类型,就不能作为ClassName
option java_outer_classname = "Person";

//如果为true,每个message和service都会被生成为一个类。如果是false,则所有的message和service都将会是java_outer_classname的内部类. (默认false)
option java_multiple_files = true;

//是否生成Service,如果这个属性为false,将不会生成Service的代码,即使已经在proto文件编写了service结构(默认false)
option java_generic_services = true;

//对生成的代码的一种优化,有三个值:SPEED,  CODE_SIZE, LITE_RUNTIME;
//表示希望生成代码是偏向执行速度,还是生成的文件大小,如果在app端,代码文件的大小是很重要的。
option optimize_for = SPEED;

//定义一个消息
message SimpleData {
  // 字段规则:required -> 字段只能也必须出现 1 次 (proto3废弃了)
  // 字段规则:optional -> 字段可出现 0 次或1次 (proto3废弃了)
  // 字段规则:repeated -> 字段可出现任意多次(包括 0)

  //字段规则 类型 名称 = 字段编号 [default = 默认值];
  string text = 1;
  int32 age = 2;
  //数组
  repeated double money = 3;
  //map集合
  map<string, int32> ages = 7;

  //deprecated设置为ture,则表示不推荐使用该字段,Java会添加@Deprecated注释
  int32 old_field = 6 [deprecated = true];

  //定义一个枚举类型
  enum Color{
    RED = 0;
    YELLOW = 1;
    BLUE = 2;
  }
  Color color = 4;

  //引用当前proto的message或import进来的proto的mesage
  ImportData importData = 5;

  //message也可以定义一个message,相当于内部类
  message InnerData{
    Color color = 3;
  }

  //这个内部类还可以引用外部类的
  message InnerData2{
    Color color = 4;
    InnerData innerDate = 5;
    ImportData importData = 6;
  }
 
  oneof Profession{//在使用时,下面的三个值,只能有一个值生效
    string math = 8; //以最后一次设置的值为准,如果最后一次设置的值为math,那么Profession的值就是math
    string compute = 9;//如果最后一次设置的值为compute,那么Profession的值就是compute
    string chemistry = 10;
  }
}

message ImportData{
  bool value = 1;
}


//定义Rpc的Service,这里需要注意:下面的方法的传入参数和返回类型都必须是message,不能是string,int32等原始类型
service SimpleDataService{
  rpc getSimpleData(ImportData) returns (SimpleData){}
}

protobuf 支持的基本类型

.proto TypeNotesC++ TypeJava TypePython Type[2]Go TypeRuby TypeC# TypePHP TypeDart Type
doubledoubledoublefloatfloat64Floatdoublefloatdouble
floatfloatfloatfloatfloat32Floatfloatfloatdouble
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32Fixnum or Bignum (as required)intintegerint
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/long[3]int64Bignumlonginteger/string[5]Int64
uint32Uses variable-length encoding.uint32int[1]int/long[3]uint32Fixnum or Bignum (as required)uintintegerint
uint64Uses variable-length encoding.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]Int64
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32Fixnum or Bignum (as required)intintegerint
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/long[3]int64Bignumlonginteger/string[5]Int64
fixed32Always four bytes. More efficient than uint32 if values are often greater than 228.uint32int[1]int/long[3]uint32Fixnum or Bignum (as required)uintintegerint
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 256.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]Int64
sfixed32Always four bytes.int32intintint32Fixnum or Bignum (as required)intintegerint
sfixed64Always eight bytes.int64longint/long[3]int64Bignumlonginteger/string[5]Int64
boolboolbooleanboolboolTrueClass/FalseClassboolbooleanbool
stringA string must always contain UTF-8 encoded or 7-bit ASCII text, and cannot be longer than 232.stringStringstr/unicode[4]stringString (UTF-8)stringstringString
bytesMay contain any arbitrary sequence of bytes no longer than 232.stringByteStringstr[]byteString (ASCII-8BIT)ByteStringstring

序列化和反序列化

  • 序列化成byte数组

    SimpleData simpleData = SimpleData.newBuilder().setText("hello")
            .setAge(18)
            .setColor(SimpleData.Color.BLUE)
            .setImportData(ImportData.newBuilder().setValue(true).build())
            .addMoney(100)
            .setOldField(111)
            .setMath("aaaa")
            .setCompute("bbbb")
            .setChemistry("cccc")
            .build();
    System.out.println(simpleData);
    byte[] bytes = simpleData.toByteArray();
    
  • 反序列化成对象

    byte[] bytes = simpleData.toByteArray();
    SimpleData simpleData1 = SimpleData.parseFrom(bytes);
    System.out.println(simpleData1);
    

DataStore Serializer

  1. protobuf-javalite

    object SimpleDataSerializer : Serializer<SimpleData> {
        override fun readFrom(input: InputStream): SimpleData {
            return try {
                SimpleData.parseFrom(input)
            } catch (exception: InvalidProtocolBufferException) {
                throw CorruptionException("Cannot read proto", exception)
            }
        }
         
        override fun writeTo(t: SimpleData, output: OutputStream) {
            t.writeTo(output)
        }
     }
    
  2. wire

    object SimpleDataSerializer : Serializer<SimpleData> {
     
        override fun readFrom(input: InputStream): SimpleData {
            return if (input.available() != 0) try {
                SimpleData.ADAPTER.decode(input)
            } catch (exception: IOException) {
                throw CorruptionException("Cannot read proto", exception)
            } else {
                SimpleData("")
            }
        }
     
        override fun writeTo(t: SimpleData, output: OutputStream) {
            SimpleData.ADAPTER.encode(output, t)
        }
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值