カスタムProtocol Buffer javanano変換ファクトリ

6400 ワード

まずProtocol Bufferとjavanaoの概念を紹介します
Protocol Buffers (a.k.a., protobuf) are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data.
Protocol Buffer(別名、protobuf)はGoogleが提供する言語中立、プラットフォーム中立、拡張可能なシーケンス化/構造化データのメカニズムである.
JavaNano is a special code generator and runtime library designed specially for resource-restricted systems, like Android. It is very resource-friendly in both the amount of code and the runtime overhead.
JavaNanoは、Androidなどのリソース制限システムのために設計された特殊なコードジェネレータとランタイムライブラリです.コード量と実行時のオーバーヘッドは非常にリソースに優しい.
仕事で引き継ぐプロジェクトでは、Protocol Buffer javananoを使用しています.コンパイルによって生成されたjavaクラスを表示すると、javananoは通常のバージョンよりも大きく去勢され、getter/setterメソッド、builderモード、Parser解析器が削除されていることがわかります.JAvananoの直接解析は問題なく、簡単で便利ですが、RxJava+Retrofitの使用に慣れた私にとって、工場統一解析を使うのは硬いニーズに違いありません.そこで質問ですが、通常バージョンの変換ファクトリ(com.squareup.retrofit 2:converter-protobuf:2.3.0)は反射で取得したParserインスタンスを用いて解析され、javananoは使用できないので、このカスタム変換ファクトリがあります.

工場の作成


ファクトリクラスには、ResponseBody/RequestBodyの2種類の変換が含まれます.
まず,ResponseBody応答メッセージの解析的変換である.
public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
  		// type class
        if (!(type instanceof Class>)) {
            return null;
        }
        Class> c = (Class>) type;
  		// type MessageNano 
        if (!MessageNano.class.isAssignableFrom(c)) {
            return null;
        }
  		// c , convert T 
        return new ProtoNanoResponseBodyConverter<>(c);
    }


ResponseBody対応変換器
final class ProtoNanoResponseBodyConverter<T extends MessageNano>
        implements Converter<ResponseBody, T> {

    private Class> c;

    public ProtoNanoResponseBodyConverter(Class> c) {
        this.c = c;
    }

    @Override
    public T convert(@NonNull ResponseBody value) throws IOException {
        T msg = null;
        try {
            //noinspection unchecked
            msg = (T) c.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        assert msg != null;
        // , mergeFrom , Response msg
        return T.mergeFrom(msg, value.bytes());
    }
}

そしてRequestBodyへの変換であり,判定条件はResponseBodyと同じである.
@Override
    public Converter requestBodyConverter
            (Type type, Annotation[] parameterAnnotations,
             Annotation[] methodAnnotations, Retrofit retrofit) {
        if (!(type instanceof Class>)) {
            return null;
        }
        if (!MessageNano.class.isAssignableFrom((Class>) type)) {
            return null;
        }
        return new ProtoNanoRequestBodyConverter<>();
    }

ResponseBody対応変換器
class ProtoNanoRequestBodyConverter implements Converter {

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/x-protobuf");

    @Override
    public RequestBody convert(@NonNull T value) throws IOException {
    	// MessageNano toByteArray 
        return RequestBody.create(MEDIA_TYPE, MessageNano.toByteArray(value));
    }
}

使用方法の概要

 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client.build())
                .addConverterFactory(ProtoNanoConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

すべての工場クラスと同じように簡単です.

All in all


カスタムファクトリのプロセスは非常に簡単で、実質的にはT.mergeFrom(msg, value.bytes())MessageNano.toByteArray(value)のさらなるパッケージにすぎず、retrofitオブジェクトの作成の使用に変換ロジックを加えることを統一し、コールバックのたびに処理する必要はありません.
ソースはこちら
転載先:https://juejin.im/post/5a58da8ff265da3e290c256c