如何从自定义Retrofit Converter向RxJavaCallAdapterFactory

时间:2017-03-21 15:32:34

标签: java android json retrofit rx-java

我的应用程序需要下载并解析一个大型JSON文件。 为了避免任何与内存相关的问题,我在1000个json对象的批量中从自定义转换器中的响应对象解析输入流。

一切正常,直到我想将解析后的对象返回给调用者的可观察对象。

我的API方法如下所示:

Observable<MyResponseStream> typesObs = api.getTypes(request.method, request.options);

响应由自定义转换器处理

public class MyResponseConverterFactory extends Converter.Factory {

    public MyResponseConverterFactory() {
    }


    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if (MyResponseStream.class.equals(type)) {
            // We will process only response where the client wait for I2ctResponseStream
            return MyResponseConverter.INSTANCE;
        }

        return null;
    }

    public static MyResponseConverterFactory create() {
        return new MyResponseConverterFactory();
    }

    final static class MyResponseConverter implements Converter<ResponseBody, MyResponseStream> {
        static final MyResponseConverter INSTANCE = new MyResponseConverter();

        @Override
        public MyResponseStream convert(ResponseBody responseBody) throws IOException {
            return new MyResponseStream(responseBody.byteStream());
        }
    }
}

MyResponseStream看起来像

public class MyResponseStream extends MyResponse<ArrayList<JSONObject>> {

    private final static int BATCH_SIZE = 1000;

    public interface ObjectsStreamListener {
        void onObjectsParsed(String parentKey, ArrayList<ObjectNode> items);
    }

    private ArrayList<ObjectNode> mItems;
    private ObjectMapper mMapper;
    private ObjectsStreamListener mListener;
    private InputStream mInputStream;                

    public MyResponseStream(InputStream inputStream) {
        super();
        mInputStream = inputStream;
        mItems = new ArrayList<>();
    }

   public void start(ObjectsStreamListener listener) {
        mListener = listener;
        if (mInputStream != null) {
            parse();
        }
    }

    private void parse() {
        try {
            mMapper = new ObjectMapper();
            JsonParser parser = mMapper.getFactory().createParser(mInputStream);
            String key;
            JsonToken currentToken = parser.nextToken();

            while (currentToken != null) {
                parser.nextFieldName();
                key = parser.getCurrentName();

                if ("method".equals(key)) {
                    method = parser.nextTextValue();
                } else if ("success".equals(key)) {
                    isSuccess = parser.nextIntValue(0) == 1;
                    Cs.e("isSuccess " + isSuccess);
                } else if ("data".equals(key)) {
                    currentToken = parser.nextToken();
                    parseData(parser);
                } else {
                    currentToken = parser.nextToken();
                }
            }
            parser.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void parseData(JsonParser parser) throws IOException {
        String currentKey;

        ObjectNode node;
        while (parser.nextToken() != null) {
            // Consume FIELD_NAME token
            parser.nextFieldName();

            // Get parent key (ex groups)
            currentKey = parser.getCurrentName();

            while (parser.getCurrentToken() == JsonToken.START_ARRAY) {
                while (parser.nextToken() == JsonToken.START_OBJECT) {
                    node = mMapper.readTree(parser);
                    mItems.add(node);
                    if (mItems.size() == BATCH_SIZE) {
                        if (mListener != null) {
                            mListener.onObjectsParsed(currentKey, mItems);
                            mItems.clear();
                        }
                    }
                }
            }

            if (!mItems.isEmpty()) {
                if (mListener != null) {
                    mListener.onObjectsParsed(currentKey, mItems);
                    mItems.clear();
                }
            }
        }
    }
}

为了获取已解析的对象,我正在注册一个监听器

typesObs.map(responseStream -> {
            responseStream.start(new MyResponseStream.ObjectsStreamListener() {
                @Override public void onObjectsParsed(String parentKey, ArrayList<ObjectNode> items) {
                    Cs.e("parentKey " + parentKey + " items " + items);
                }
            });
            return responseStream;
        })

这种方法很有效,但它看起来不是一个好的解决方案,因为我没有以任何方式利用RxJava observable。

我的问题:有没有办法从转换器调用结果可观察onNext()? 我想替换

mListener.onObjectsParsed(currentKey, mItems);

类似

retrofit.getRxCallAdapterFactory().getCallerObservable().onNext(items)

1 个答案:

答案 0 :(得分:1)

您可以采取的一种方法是创建适配器而不是转换器。

这种方法可以按以下顺序运作:

  1. 检查类型是否为`static Scanner scan; public static void main(String[] args) { scan = new Scanner(System.in); double a = Math.pow(getHeight(), 2); System.out.println(a); double b = Math.pow(getWidth(), 2); double c = a + b; System.out.println(Math.sqrt(c)); scan.close(); }`
  2. 使用Observable<MyResponseStream>检索retrofit.callAdapter(...)
  3. 的适配器
  4. 创建一个自定义适配器,将observable的创建委托给先前检索的适配器,然后应用操作为返回的observable创建Observable<Response>