android中protobuf的简单使用

protobuf 是什么?  为什么要用到?

protobuf 是二进制存储 所以比 json传输更快  更易于跨平台开发  但是读写更麻烦  

没关系,google已经帮我们处理好了   现在我们只用站在巨人的肩膀上就行

先来看一个简单的protobuf 类  类名定义为 Result  Result 类中定义个对象

message PMessage {
    int32 code = 1;        
    string name = 2;         
}

int32对应  java的int   int64对应java的long

然后把他导入android studio中  生成java文件

这里就不讲解了  自行百度  

因为我项目是用retrofit2 + rxjava网络请求   所以就基于此来演示

1、解析

网络请求结果   ResponseBody  

Result.PMessage pResult = Result.PMessage.newBuilder().mergeFrom(response.byteStream()).build();

简单吧   如果你是用其他http请求框架    都有请求结果转二进制流的方法  只需要把二进制流丢进 mergeFrom方法即可

mergeFrom看生成的java文件代码   此方法支持ByteString   byte[]  InputStream等

2、封装

看到这里,会不会想到  一个项目 跟后台网络通信肯定不会只涉及到一个  protobuf类   多个类该怎么封装解析代码呢?

我们来看看newBuilder()代码

在看看 DEFAULT_INSTANCE是什么

PMessage 是通过Builder来初始化的

在来看看Builder类型

是google定义的  

com.google.protobuf.GeneratedMessageV3.Builder<Builder>

那么开始封装解析库

先改造下上面的类

message PMessage {
    int32 code = 1;  //公共响应码      
    string name = 2; //data对应的protobuf类
    bytes data = 3;  // 特定的protobuf类数据     
}

假设我们需要解析个类 aaaa

message aaaa{
    int32 age= 1;        
    string name = 2;            
}

那么PMessage中   name就是aaaa    data即是aaaa对象的bytes数据   自行跟后台定义好

public class HttpResultAnalysis {
    public static TreeMap<String, GeneratedMessageV3.Builder<?>> MessageMap =
            new TreeMap<>();

    static {
        //需要解析的类  假设是  aaaa
        MessageMap.put("aaaa", Result.aaaa.newBuilder());
    }

    public static void disposeResult(ResponseBody response,DisposeResultListener disposeResultListener){
        try{
            //解析基类
            Result.PMessage result  = Result.PMessage.newBuilder().mergeFrom(response.byteStream()).build();
            //result中 name字段对应本地解析的className  data对应本地对象的字节流
            if (!TextUtils.isEmpty(result.getName())) {
                com.google.protobuf.GeneratedMessageV3.Builder<?> mBuilder = MessageMap.get(result.getName());
                if (mBuilder == null) {
                    throw new IllegalAccessException("protobuf类本地未定义");
                }
                /**
                 * 千万记得调用clear  否则会有重复数据  因为我是在上面静态块中调用newBuilder()   而不是在此处解析调用
                 *
                 * see   newBuilder() -> toBuilder()->
                 *
                 * new Builder().mergeFrom(this)   看到了么  如果对象有值   则会先把本身的值重新赋值 在加入新数据
                 */

                Object c = mBuilder.clear().mergeFrom(result.getData()).build();
                disposeResultListener.onSuccessObject(c);
                //用自定义监听返回调用的地方   Result.PMessage pMessage = (Result.PMessage) e;即可获取数据
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public interface DisposeResultListener {
        void onSuccessObject(Object c);
    }
}

简单封装就到这里了   可以根据实际情况来处理

3、本地创建对象

上面只是解析网络数据    本地该怎么初始化protobuf类呢

1、Result.PMessage pMessage = Result.PMessage.newBuilder().clear()
        .setData(ByteString.copyFrom(new byte[]{}))
        .setName("aaaa")
        .build();

2、接上面解析回调
   Result.PMessage pMessage = (Result.PMessage) c;
   pMessage.toBuilder().setData(ByteString.copyFrom(new byte[]{})).build();

 

4、protobuf中  map类型是只可读 如果传递的map需要本地修改  需要自己定义个map类中转

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值