【问题标题】:how to request protobuf using volley?如何使用 volley 请求 protobuf?
【发布时间】:2013-06-12 04:23:52
【问题描述】:

任何人都有一个例子,你在其中使用 volley 读取 protobuf?。我读过你可以实现 ProtobufRequest 类,但我找不到它的文档。感谢您的帮助。

【问题讨论】:

    标签: android protocol-buffers android-volley


    【解决方案1】:

    我已经完成了,工作还可以,希望对您有所帮助。首先创建如下扩展Request的ProtobufRequest类,Request是Volley中的基本请求类,然后​​,您可以创建自定义请求扩展ProtobufRequest自定义doParse()。仅供参考。

    RequestData 是 SomeProto 消息,

    private static final int SOCKET_TIMEOUT = 30000;
    
    /** Content type for request. */
    private static final String PROTOCOL_CONTENT_TYPE = "application/x-protobuf";
    
    private static final Object sDecodeLock = new Object();
    
    private RequestData mRequestData;
    private BaseCallback mCallback;
    
    public ProtobufRequest(RequestData data, BaseCallback callback) {
        super(Method.POST, Constants.SERVER_URL, callback);
        // TODO Auto-generated constructor stub
        mRequestData = data;
        mCallback = callback;
        this.setRetryPolicy(getRetryPolicy());
    }
    
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Charset", "UTF-8");
        headers.put("Content-Type", "application/x-protobuf");
        headers.put("Accept", "application/x-protobuf");
    
        return headers;
    }
    
    @Override
    public String getBodyContentType() {
        return PROTOCOL_CONTENT_TYPE;
    }
    
    @Override
    public RetryPolicy getRetryPolicy() {
        RetryPolicy retryPolicy = new DefaultRetryPolicy(SOCKET_TIMEOUT,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
        return retryPolicy;
    }
    
        /**
        ** write the protobuf data to http request,it is very important
        */
    @Override
    public byte[] getBody() throws AuthFailureError {
        if (mRequestData == null) {
            return super.getBody();
        } else {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
    
                baos.write(mRequestData.toByteArray());
            } catch (IOException e) {
                return super.getBody();
            }
    
            return baos.toByteArray();
        }
    }
    
    @Override
    protected void deliverResponse(Object arg0) {
        mCallback.onResponse(arg0);
    }
    
        /**
        ** parse the response result
        */
    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        synchronized (sDecodeLock) {
            try {
                return doParse(response, HttpHeaderParser.parseCacheHeaders(response));
            } catch (OutOfMemoryError e) {
                return Response.error(new ParseError(e));
            }
        }
    }
    
    abstract protected Response<T> doParse(NetworkResponse response, Entry entry)
    
    
    public interface BaseCallback extends Listener<Object>, ErrorListener {
    
    }
    

    【讨论】:

      【解决方案2】:

      来自:cmcneil 添加代码以防链接失效。 Volley 或 Protocol Buffers 最终应该会有一个正式的实现,所以请在必要时更新它。

      import com.android.volley.AuthFailureError;
      import com.android.volley.DefaultRetryPolicy;
      import com.android.volley.NetworkResponse;
      import com.android.volley.ParseError;
      import com.android.volley.Request;
      import com.android.volley.Response;
      import com.android.volley.Response.Listener;
      import com.android.volley.RetryPolicy;
      import com.android.volley.toolbox.HttpHeaderParser;
      import com.google.protobuf.MessageLite;
      
      import java.util.HashMap;
      import java.util.Map;
      
      /**
       * Created by carson@convox.org on 5/10/15.
       */
       public class ProtoBufRequest<ReqT extends MessageLite, RespT extends MessageLite> extends Request<RespT> {
      
          private ReqT request;
          private final Class<RespT> responseType;
          private final Listener<RespT> listener;
          private static final String PROTOCOL_CONTENT_TYPE = "application/x-protobuf";
          private static final int SOCKET_TIMEOUT = 30000;
      
          public ProtoBufRequest(int method, String url, ReqT data, Class<RespT> responseType,
                                 Listener<RespT> listener, Response.ErrorListener errorListener) {
              super(method, url, errorListener);
              this.listener = listener;
              this.request = data;
              this.responseType = responseType;
          }
      
          @Override
          public Map<String, String> getHeaders() throws AuthFailureError {
              Map<String, String> headers = new HashMap<String, String>();
              headers.put("Charset", "UTF-8");
              headers.put("Content-Type", PROTOCOL_CONTENT_TYPE);
              headers.put("Accept", PROTOCOL_CONTENT_TYPE);
      
              return headers;
          }
      
          @Override
          public byte[] getBody() throws AuthFailureError {
              if (request == null) {
                  return super.getBody();
              }
              return request.toByteArray();
          }
      
      
          @Override
          protected Response<RespT> parseNetworkResponse(NetworkResponse response) {
              try {
                  if (responseType == null) {
                      throw new IllegalArgumentException("The response type was never provided.");
                  }
                      RespT responseInstance = responseType.newInstance();
                      return (Response<RespT>) Response.success(
                              responseInstance.newBuilderForType().mergeFrom(response.data).build(),
                              HttpHeaderParser.parseCacheHeaders(response));
              } catch (Exception e) {
                  e.printStackTrace();
                  return Response.error(new ParseError(e));
              }
          }
      
          @Override
          public String getBodyContentType() {
              return PROTOCOL_CONTENT_TYPE;
          }
      
          @Override
          public RetryPolicy getRetryPolicy() {
              RetryPolicy retryPolicy = new DefaultRetryPolicy(SOCKET_TIMEOUT,
                      DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
              return retryPolicy;
          }
      
          @Override
          protected void deliverResponse(RespT response) {
              listener.onResponse(response);
          }
      }
      

      【讨论】:

        【解决方案3】:

        这不是一个例子,我自己(还没有)做过,但我会这样做:

        一种方法是扩展 JsonObjectRequest 并将每个协议缓冲区序列化和反序列化为 Json 使用:

         Message someProto = SomeProto.getDefaultInstance();
         String jsonFormat = JsonFormat.printToString(someProto);
        
        Message.Builder builder = SomeProto.newBuilder();
        String jsonFormat = _load json document from a source_;
        JsonFormat.merge(jsonFormat, builder);
        

        见:https://code.google.com/p/protobuf-java-format/

        否则,如果您想将协议缓冲区序列化发送到 byte[],您可以扩展 Request&lt;T&gt;。您将为请求正文/有效负载覆盖public byte[] getBody(),并且 受保护的Response&lt;Message&gt; parseNetworkResponse(NetworkResponse response) 的答案。

        然后您将使用以下函数来序列化协议缓冲区。

        byte[] toByteArray();
        
        parseFrom(byte[] data);
        

        如果您有解决方案,请不要忘记分享。

        【讨论】:

          【解决方案4】:

          只要把它贴在这里以防它有用: 我搜索了很多,寻找一种通用的方法来做类似于jeff wang 的答案。我找不到任何东西,所以我写了这个。 让我知道你是否有办法摆脱那里未经检查的演员...

          ProtobufRequest.java

          public class ProtoBufRequest<ReqT extends Message, RespT extends Message> extends Request<RespT> {
          
            private ReqT request;
            private final Class<RespT> responseType;
            private final Listener<RespT> listener;
            private static final String PROTOCOL_CONTENT_TYPE = "application/x-protobuf";
            private static final int SOCKET_TIMEOUT = 30000;
          
            public ProtoBufRequest(int method, String url, ReqT data, Class<RespT> responseType,
                                   Listener<RespT> listener, Response.ErrorListener errorListener) {
                super(method, url, errorListener);
                this.listener = listener;
                this.request = data;
                this.responseType = responseType;
            }
          
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> headers = new HashMap<String, String>();
                headers.put("Charset", "UTF-8");
                headers.put("Content-Type", PROTOCOL_CONTENT_TYPE);
                headers.put("Accept", PROTOCOL_CONTENT_TYPE);
          
                return headers;
            }
          
            @Override
            public byte[] getBody() throws AuthFailureError {
                if (request == null) {
                    return super.getBody();
                }
                return request.toByteArray();
            }
          
          
            @Override
            protected Response<RespT> parseNetworkResponse(NetworkResponse response) {
                try {
                    if (responseType == null) {
                        throw new IllegalArgumentException("The response type was never provided.");
                    }
                        RespT responseInstance = responseType.newInstance();
                        return (Response<RespT>) Response.success(
                              responseInstance.newBuilderForType().mergeFrom(response.data).build(),
                                HttpHeaderParser.parseCacheHeaders(response));
                } catch (Exception e) {
                    e.printStackTrace();
                    return Response.error(new ParseError(e));
                }
            }
          
            @Override
            public String getBodyContentType() {
                return PROTOCOL_CONTENT_TYPE;
            }
          
            @Override
            public RetryPolicy getRetryPolicy() {
                RetryPolicy retryPolicy = new DefaultRetryPolicy(SOCKET_TIMEOUT,
                        DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
                return retryPolicy;
            }
          
            @Override
            protected void deliverResponse(RespT response) {
                listener.onResponse(response);
            } 
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-02-28
            • 2015-07-25
            • 1970-01-01
            相关资源
            最近更新 更多