Android中使用Retrofit和RxJava从JSON数组中一一获取JSON对象

2023-12-23

我正在使用 Retrofit 来访问返回 json 数组的网络 api。我正在使用以下代码这样做-

Observable<MyJson[]> response = (Observable<MyJson[]>)mNetworkService.getReadyObserverable(mNetworkService.getNetworkServiceApi().getMyDataJsons(), MyJson.class, true, useCache);
        mAirlineSubscription = response.subscribe(new Observer<MyJson[]>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "getData completed..");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError: "  + e.getLocalizedMessage());
            }

            @Override
            public void onNext(MyJson[] myJsonData) {
                //I want here json data one by one
            }

但我的问题是 json 数据数组被完全下载,然后才onNext被叫。在这里我想要onNext当 Retrofit 下载第一个 json 对象时应该被调用myData[]json 数组并继续,直到我的所有 json 对象myData[]得到下载。这样,我的 UI 看起来响应更快,用户交互也更好。

任何人都可以帮忙解决这个问题吗?


尽可能快地一一接收元素?
不想等待所有内容都下载完毕?

解决办法是:用注解声明retrofit接口的方法@Streaming并使用Observable<ResponseBody>作为返回值。然后,通过使用flatMap(), 转变ResponseBody到 POJO 系列(Observable<TYPE>).

Example:

  1. 声明改造接口:

    public interface HugeJsonApi {
    
    String SERVICE_ENDPOINT = "https://raw.githubusercontent.com";
    
    @Streaming
    @GET("/zemirco/sf-city-lots-json/master/citylots.json")
    Observable<ResponseBody> get();
    }
  2. 像这样使用它:

    public void playHugeJsonSample() {
    
        HugeJsonApi hugeJsonApi = RestUtils.createService(HugeJsonApi.class, HugeJsonApi.SERVICE_ENDPOINT);
    
        Handler handler = new Handler(Looper.getMainLooper());
        hugeJsonApi.get()
                .flatMap(responseBody -> convertObjectsStream(responseBody, gson, Feature.class))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Feature>() {
    
                    @Override
                    public void onStart() {
                        super.onStart();
                        request(1);
                    }
    
                    @Override
                    public void onNext(Feature feature) {
                        Log.i(TAG, gson.toJson(feature));
                        counter[0]++;
                        request(1);
                    }
    
                    @Override
                    public void onCompleted() {
                        Log.i(TAG, "onCompleted() called. Fetched elements:" + counter[0]);
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        Log.e(TAG, "something went wrong", e);
                    }
                });
    }
    
    @NonNull
    private static <TYPE> Observable<TYPE> convertObjectsStream(ResponseBody responseBody, Gson gson, Class<TYPE> clazz) {
        Type type = TypeToken.get(clazz).getType();
        return Observable.create(SyncOnSubscribe.<JsonReader, TYPE>createStateful(
                // initialize the reader
                () -> {
                    try {
                        JsonReader reader = gson.newJsonReader(responseBody.charStream());
                        reader.beginObject();
                        return reader;
                    } catch (IOException e) {
                        e.printStackTrace();
                        RxJavaHooks.onError(e);
                    }
                    return null;
                },
                // read elements one by one
                (reader, observer) -> {
    
                    if (reader == null) {
                        observer.onCompleted();
                        return null;
                    }
    
                    try {
                        if (reader.hasNext()) {
                            TYPE t = gson.fromJson(reader, type);
                            observer.onNext(t);
                        }
                        else {
                            observer.onCompleted();
                        }
    
                    } catch (IOException e) {
                        e.printStackTrace();
                        observer.onError(e);
                    }
    
                    return reader;
                },
                // close the reader
                reader -> {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                            RxJavaHooks.onError(e);
                        }
                    }
                }
    
        ));
    }

这是可行的示例:

https://github.com/allco/RetrofitAndRxJava https://github.com/allco/RetrofitAndRxJava

它需要 180+Mb Json 并将其解析为真正的流。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android中使用Retrofit和RxJava从JSON数组中一一获取JSON对象 的相关文章

随机推荐

  • 如何使用存储库接口在 Spring Data 中通过其嵌套对象的 objectId 查找集合?

    我在 MongoDB 中有一个集合 其中包含如下项目 id ObjectId 53e4d31d1f6b66e5163962e3c name bob nestedObject id ObjectId 53f5a623cb5e4c1ed4f6c
  • 在适用于 iOS 的 HTML5 中包含 SVG

    我想在 HTML5 网页中包含 SVG 图像 通过 JavaScript 与此 SVG 交互 并应用 CSS 样式 如果可能的话 我更愿意将 SVG 保存在单独的文件中 我希望能够离线使用该网页 因此希望推荐的任何解决方案都与此兼容 请有人
  • 使用通用键值对对字典列表列表中的值求和

    如何对字典列表列表中的重复元素求和 样本清单 data user 1 rating 0 user 2 rating 10 user 1 rating 20 user 3 rating 10 user 4 rating 4 user 2 ra
  • Android 5.1推送通知图标为空白

    当使用 Parse 进行推送通知时 我们的应用程序始终显示应用程序的启动器图标 在最新的 Android 5 1 版本中 该图标显示为空白 白色方块 我尝试在元数据中设置图标
  • 如何在 Bash 中将 `4-7` 替换为 `4,5,6,7`

    Goal 我有一根长绳子s它表示由逗号和破折号分隔的一系列数字 见下文 当多个数字彼此跟随时 将写入两个极端数字并用破折号分隔 例如 该系列4 5 6 7写成4 7 我的目标是扩展这个字符串 使所有数字都用逗号分隔 4 7应该成为4 5 6
  • C# 获取 XML 标签值

    我有一个名为BackupManager xml
  • 如何防止任务管理器中的应用程序被杀死?

    我正在开发一个家长控制应用程序 用 WPF 编写 并且希望禁止任何人 包括管理员 终止我的进程 不久前 我在网上发现了以下代码 它几乎可以完美运行 只是有时不起作用 static void SetAcl var sd new RawSecu
  • ReactJS 如何在 React 中切换页面?

    因此 来自 Angular AngularJS 背景的人有状态 每个状态都是一个单独的页面 例如 在社交网络中 您可以有一个包含您的提要的状态 一个包含您的朋友列表的状态 或者一个查看个人资料的状态等 非常简单 对我来说 React 没有那
  • 在屏幕中央启动 Facebook 共享弹出窗口

    以下代码运行良好 并在屏幕上启动 Facebook 弹出窗口 但该弹出窗口未居中 a href http www facebook com share php u a
  • JavaScript 将
    替换为 \n

    我刚刚使用 JavaScript 和 PHP 在 MySQL 数据库中存储了一段文本并替换 n with br 我现在遇到的问题是 当我尝试使用 PHP 检索文本时 它会将其打印出来 br Dear Sir Maddam br This i
  • Django 动态 OR 查询

    我有一个MultipleChoiceField在保存汽车制造商的表格上 我想将我的汽车数据库过滤到已检查的品牌 但这会导致问题 我如何获得所有Q make 动态声明 我如何开始 value1 value2 我想如何结束 Q col valu
  • html 中的大括号和百分号是什么意思?

    我正在学习如何在 Django 框架中开发网站 我对模板 html 文件有一些不明白的地方 我看到教程使用了大括号 等 将逻辑嵌入到代码中 但是当我尝试在非 Django 服务器 Apache 中使用此语法时 此语法未被解释 我可以看到我的
  • 为nginx添加LUA模块

    我在 redhat 7 5 服务器上 rpm 安装了 nginx 1 12 它还有 LUA 5 1 4 我下载了 lua nginx module 0 10 13 tar ball 并将其放在 etc nginx modules 下 但我无
  • 如何让jni.h被发现?

    在Ubuntu 12 04中 我安装了来自sun oracle的jdk7 什么时候locate jni h 它打印多个位置 usr lib jvm java 6 openjdk amd64 include jni h usr lib jvm
  • 如何将 Python 字典树化?

    我正在构建一个电报机器人 并且想要转换 json 响应 例如下面我将其转换为字典的响应 message id 445793 from id 106596774 is bot false first name Komron last name
  • C 程序在不设置 LD_LIBRARY_PATH 的情况下链接共享库

    我正在阅读 GCC 简介 它说一个包是否同时包含 a 和 so gcc 更喜欢共享库 默认情况下 加载程序仅在一组预定义的系统目录中搜索共享库 例如 usr local lib and usr lib 如果库不位于这些目录之一 则必须将其添
  • 如何在 swift 中制作可设计的文本字段代码类

    我是编程和 iOS 开发的初学者 我想制作一个 swift 文件 其中包含用于制作可设计文本字段的代码 因此我不会通过编码来编辑 UI 元素显示 所有将要编辑的 UI 我将在 Interface builder 中编辑它 我需要在 UITe
  • wx.html2.WebView 和屏幕阅读器

    在 wxPython 4 0 Phoenix 中 我尝试将 wx html2 WebView 与屏幕阅读器一起使用 无论是使用 JAWS 还是 NVDA 我都必须在小部件上单击鼠标左键才能在可访问的 Web 界面中查看我的页面 这是我的代码
  • Argparse 和 ArgumentDefaultsHelpFormatter。选择 sys.stdin/stdout 作为默认值时的默认值格式

    我对使用 argparse 的 ArgumentDefaultsHelpFormatter 类格式化程序感兴趣 我的程序有几个子命令 默认情况下 输入和输出参数分别设置为 sys stdin 和 sys stdout 然而 这两个参数的格式
  • Android中使用Retrofit和RxJava从JSON数组中一一获取JSON对象

    我正在使用 Retrofit 来访问返回 json 数组的网络 api 我正在使用以下代码这样做 Observable