使用 RXJava 进行缓存处理

2024-02-12

我正在尝试使用 rxJava 实现此工作流程,但我确定我是否误用或做错了事情。

  • 用户要求登录
  • 如果登录结果在缓存中可用,则“发出”缓存的登录结果
  • 否则,如果一切成功,则实际执行对 Web 服务的请求并缓存结果
  • 如果发生错误,最多重试 3 次,如果有第 4 次,则清除缓存。

这是我的完整代码片段。

public class LoginTask extends BaseBackground<LoginResult> {
  private static CachedLoginResult cachedLoginResult = new CachedLoginResult();
  private XMLRPCClient xmlrpcClient;
  private UserCredentialsHolder userCredentialsHolder;

  @Inject
  public LoginTask(XMLRPCClient client, UserCredentialsHolder userCredentialsHolder) {
    this.xmlrpcClient = client;
    this.userCredentialsHolder = userCredentialsHolder;
  }

  @Override
  public LoginResult performRequest() throws Exception {
    return UserApi.login(
        xmlrpcClient,
        userCredentialsHolder.getUserName(),
        userCredentialsHolder.getPlainPassword());


  }

  @Override
  public Observable<LoginResult> getObservable() {
    return cachedLoginResult.getObservable()
        .onErrorResumeNext(
            Observable.create(
                ((Observable.OnSubscribe<LoginResult>) subscriber -> {
                  try {
                    if (!subscriber.isUnsubscribed()) {
                      subscriber.onNext(performRequest()); // actually performRequest
                    }
                    subscriber.onCompleted();
                  } catch (Exception e) {
                    subscriber.onError(e);
                  }
                })
            )
                .doOnNext(cachedLoginResult::setLoginResult)
                .retry((attempts, t) -> attempts < 3)
                .doOnError(throwable -> cachedLoginResult.purgeCache())
        );
  }


  private static class CachedLoginResult {
    private LoginResult lr = null;
    private long when = 0;

    private CachedLoginResult() {
    }

    public boolean hasCache() {
      return lr != null && when + TimeUnit.MILLISECONDS.convert(30, TimeUnit.MINUTES) > System.currentTimeMillis();
    }

    public void setLoginResult(LoginResult lr) {
      if (lr != null) {
          this.lr = lr;
          this.when = System.currentTimeMillis();
      }
    }

    public void purgeCache() {
      this.lr = null;
      this.when = 0;
    }

    public Observable<LoginResult> getObservable() {
      return Observable.create(new Observable.OnSubscribe<LoginResult>() {
        @Override
        public void call(Subscriber<? super LoginResult> subscriber) {
          if (!subscriber.isUnsubscribed()) {
            if (hasCache()) {
              subscriber.onNext(lr);
              subscriber.onCompleted();
            } else {
              subscriber.onError(new RuntimeException("No cache"));
            }
          }
        }
      });
    }
  }
}

由于我无法找到任何类似的示例,并且我在 1 天前开始“玩”rxjava,所以我不确定我的实现。

感谢您的时间。


我认为这段代码没问题,干得好:)

你使用是正确的Observable.create在你的LoginTask因为否则调用结果可以在内部缓存,然后retry没有多大帮助...

我认为这对于CachedLoginResult's Observable。在这里您可以使用以下方法简化代码Observable.justand Observable.error实用方法,例如:

public Observable<LoginResult> getObservable() {
  if (hasCache()) {
      return Observable.just(lr);
  } else {
      return Observable.error(new RuntimeException("No cache"));
  }
}

Note: just存储您告诉它在内部发出的值,以便重新订阅将始终产生该值。这就是我上面暗示的,你不应该这样做Observable.just(performRequest()).retry(3)例如,因为performRequest只会被调用一次。

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

使用 RXJava 进行缓存处理 的相关文章

  • Java ZIP - 如何解压缩文件夹?

    是否有任何示例代码 如何将 ZIP 中的文件夹部分解压到我想要的目录中 我已将文件夹 FOLDER 中的所有文件读取到字节数组中 如何从其文件结构创建 我不确定你所说的部分是什么意思 您的意思是在没有 API 帮助的情况下自己完成吗 如果您
  • 通过拖动块来选择多个项目

    首先 让我告诉你 我对此感到压力很大 因为我什至不知道概念 方法名称 所以我什至无法在谷歌中搜索它 因为我不知道关键字 但我会尝试我的最好解释一下 请随意修改我的内容和标题 我想要实现的是 我的视图组包含许多子视图 或者它可以是 GridV
  • 具有多个注释的方法上的 AspectJ 切入点

    使用加载时编织 纯 AspectJ 我们有2个注释 Time and Count 以及一些带注释的方法 Time name myMethod1Time Count name myMethod1Count public void myMeth
  • 改变换行行为

    我可以在 TextView 中使用 Spannable 创建具有不同外观 下划线 删除线等的跨度 我怎样才能做同样的事情来改变换行行为 特别是 我不希望电子邮件地址在中间换行 我希望它像一个单词一样 I tried 包裹在一起跨度 http
  • 将 try catch finally 块放入另一个 finally 块中

    try catch finally try catch finally 上面的代码好不好 是的 你可以这样做 实际上 在处理想要正确关闭的流时 您甚至需要这样做 InputStream in try catch finally try in
  • Android Studio 1.0 在 dexDebug 或 dexRelease 上构建失败

    我最近从 Android Studio 0 9 2 升级到 1 0 包括 Gradle 插件版本 1 0 0 并且在构建项目时遇到问题 每当我构建时 我都会在 dexDebug 或 dexRelease 步骤中收到以下异常 UNEXPECT
  • 如何知道一个点是否在复杂的 3D 形状内(.ply 文件)

    我正在研究一个Java女巫项目真是要了我的命 经过几天在不同论坛上的研究 寻找我真正需要的东西 我来寻求你的帮助 我的数据 ply 文件 包含由许多三角形组成的 3D 形状 一个点 3D坐标 我想知道这个点是否包含在复杂的 3D 形状内 我
  • 重构 google 的 NetworkBoundResource 类以使用 RxJava 而不是 LiveData

    谷歌的android架构组件教程here https developer android com topic libraries architecture guide html有一部分解释了如何抽象通过网络获取数据的逻辑 在其中 他们使用
  • android中ScrollView中的图像

    在我的应用程序中 我想放置一个 png 文件 并且希望它在横向和纵向模式下都被视为滚动图像 请建议代码或示例 要使您的 Imageview 在高度不适合时滚动 您可以在 xml 中的 ScrollView 内添加一个 ImageView 并
  • java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException

    我想将 apache cli 添加到我的应用程序中 但我有问题 当我尝试运行它时显示这些错误 Error A JNI error has occurred please check your installation and try aga
  • 以编程方式安装 Android apk 作为测试框架的一部分

    我正在尝试以编程方式安装 apk 但运气不佳 我正在设置一个针对物理设备的自动化测试框架 并且我希望测试设备在运行测试之前从构建服务器检索最新的 apk 虽然我知道没有通用的方法可以在未经用户同意的情况下实际安装 apk 但我很好奇在开发人
  • java.lang.OutOfMemoryError:尝试将 Java 对象转换为 Json 字符串时的 Java 堆空间

    我尝试将 csv 文件转换为 200K 对象的 Json 文件 其中对象代表 csv 中的 1 行 我在 32 位上安装了 Java 并且项目配置 VM 参数 Xmx1024m 但是我得到 Exception in thread main
  • 注释处理工具<-检查有效注释

    I have ColumnMetadata index 1 ColumnMetadata index 2 ColumnMetadata index 3 我必须使用 APT 检查索引号是否唯一 我不知道该怎么做 我看不懂教程 一般我在网上找资
  • Android Wear Overlay 传递触摸事件

    我有一个 Android Wear 应用程序 其中我使用透明的覆盖视图来接收触摸事件 我需要能够接收屏幕上任何位置发生的所有触摸事件 并且还能够看到它们的坐标 我发现的所有研究都表明我无法接收所有触摸事件并将其传递 然而 and 都在做这样
  • Android 预安装检测

    我的 Android 应用程序将被预安装 我想继续跟踪预安装的应用程序 为此 我需要以某种方式保存密钥或标志 这意味着该应用程序是预安装的 我会将此密钥添加到后端的每个请求中并对其进行分析 我对此有疑问 有一个问题是关于从 Google P
  • AAR 可以包含传递依赖吗? [复制]

    这个问题在这里已经有答案了 现在我有一个库项目 比如项目 Foo 它依赖于像 OkHttp 这样的库 现在 Foo 有一个 Maven 构建步骤 可以生成 AAR 并将其推送到公共位置 现在假设我有项目 B 我们将其称为 Bar Bar是一
  • 膨胀类 android.support.design.internal.BottomNavigationView 时出错

    我正在制作我的第一个应用程序 这是一个简单的应用程序 带有启动屏幕和主要活动 现在我有两个构建变体 免费版本 活动底部有 Admob 横幅 付费版本 该应用程序不会在底部显示 admob 横幅 而是将其替换为用于切换活动的底部导航视图 我将
  • 智能手机可以通过 3G/4G 进行点对点通信吗?

    我正在尝试编写一个应用程序 将数据从一个 Android 设备传输到另一个 Android 设备 但这些设备很可能位于城市 州或国家的不同部分 直接的方法是拥有一台中央服务器 或任何类型的服务器 但我试图避免使用中央服务器 我试图传递的数据
  • Java:将秒转换为分钟、小时和天[重复]

    这个问题在这里已经有答案了 任务是 输出应如下所示 最好回显输入 您输入了 500 000 秒 即 5 天 18 小时 53 分钟 20 秒 5天18 53 20小时 我该怎么做呢 最容易理解和做到的方法是什么 讲师还说 没有硬编码 我不太
  • 如何在不显示父活动的情况下将一个全屏对话框片段替换为另一个全屏对话框片段?

    我有一个使用单个自定义 DialogFragment 类的活动 它的外观是数据驱动的 因此不同的调用看起来可能相当不同 它是 全屏 即 setStyle DialogFragment STYLE NO FRAME android R sty

随机推荐

  • 派生类型中的可变长度数组

    我主要使用 Python 进行科学编程 并没有大量的 Fortran 90 95 经验 对于我的一个项目 我想定义一个派生类型并为该类型重载一堆运算符 至关重要的是 我希望派生类型的变量之一成为可变长度的数组 至少 我在代码的不同部分需要两
  • 删除 tar 生成的尾随空字符

    我正在尝试压缩一些文件并通过 php passthru 命令将它们传递给用户 问题是 尽管 tar 文件应该只有 2k 大小 但它始终是 10240 有趣的数字对吗 所以我把它分解为 sh 4 1 tar czf test wc c 102
  • iPhone 上针对 RTL 语言的翻转布局

    这是我的问题 我已将我的应用程序本地化为阿拉伯语 它实际上与常规本地化略有不同 因为我有不同的目标 每种语言一个 在模拟器上 由于自动布局和约束的前导 尾随部分 视图被正确翻转 但我似乎无法在设备上获得相同的结果 AutoLayout RT
  • bash 创建带有序列号的目录

    我正在创建一个在 OS X 上运行的脚本 该脚本将由新手用户经常运行 因此希望通过每次创建一个新的目录结构并在最后一个上使用 n 1 来保护目录结构 target001下一次运行创建target002 到目前为止我有 lastDir fin
  • 重置按钮处理点击后执行 Javascript 操作

    如何立即执行某项操作after an
  • EF Core 查询存储过程映射到类型

    我有一个项目需要查询数据库并将结果返回到 Web api 有几个由数据库管理员即时创建的存储过程 它们有一个 UI 用于创建存储过程的定义及其名称 而 Web API 服务仅调用该 SP 并应返回结果 根据下面的代码 我无法将返回对象获取到
  • 我在 for 循环中使用 let 关键字给出了语法错误:意外的标识符

    我在 for 循环中使用 let 关键字 如下所示 for let methd1 in servUrl let methd methd1 for let pth1 in servUrl methd let pth pth1 app meth
  • 有没有办法使用 cron 重新启动 pm2 进程,但前提是它尚未运行?

    我想通过 PM2 重新启动我的 Node Js 应用程序 pm2 restart app js 使用 crontab 但仅当应用程序尚未运行时 例如 如果我的服务器崩溃并重新启动并且 pm2 没有重新启动 即使它正在运行 上面的命令也会重新
  • TensorFlow的map_fn仅在CPU上运行

    我在尝试获取 TensorFlow 时遇到了一个奇怪的问题map fn在我的 GPU 上运行 这是一个最小的损坏示例 import numpy as np import tensorflow as tf with tf Session as
  • Log4net 日志记录不适用于并行线程

    我在随机数上使用基本的 Parallel Foreach 循环来使用 log4net 记录数字本身 这是我在并行线程上记录 5000 条消息的代码 Logger logger new Logger var numbers Enumerabl
  • Javascript 中是否按顺序执行相等的超时?

    假设我这样做 setTimeout foo 0 setTimeout bar 0 我可以确定 foo 会在 bar 之前开始执行吗 如果我使用 1 10 或 100 的超时值代替 0 会怎么样 简单的实验表明 在超时值相等的情况下 超时目标
  • XElement 添加一个 xmlns

    我正在使用 Linq to XML 创建一个新的 XML 文件 我从现有的 XML 文件中获取该文件的某些部分 我为此使用以下代码 var v2 new XDocument new XDeclaration 1 0 utf 16 new X
  • 使用 Mongoose 更新 _id = :id 的记录

    我正在尝试使用 Mongoose 更新现有记录 插入可以 但更新不行 这是我的片段 app post submit function req res var my visit new models visits date req body
  • 在 RedShift 中将值拆分为多行

    如何将字段 例如 CSV 字符串 拆分为多行的问题已经得到解答 将值拆分为多行 https stackoverflow com questions 13159526 split values over multiple rows 然而 这个
  • 如何在Java Web应用程序中动态设置会话超时?

    我需要为我的用户提供一个 Web 界面来更改会话超时间隔 因此 不同安装的 Web 应用程序的会话超时时间可能不同 但它们的会话超时时间不同 web xml不可能不同 有没有办法以编程方式设置会话超时 以便我可以使用 例如ServletCo
  • Greasemonkey 中未定义“文档”

    不到十分钟前 我决定为 Greasemonkey 编写第一个剧本 我对此的经验为零 另外 我的 JavaScript 有点生疏了 因为自从我上次用它编写代码以来已经有一段时间了 但我不明白为什么 Greasemonkey 给我这个错误 Li
  • PDF压缩库/工具

    我正在开发一个项目来减小 PDF 的大小并对其进行压缩 我想知道市场上是否有任何非常好的工具 库 NET 我确实尝试了一些工具 例如 Onstream Compression 但结果并不令人满意 一些额外的 兆 字节可以很容易地从 PDF
  • 从 Java 应用程序中执行 Pig

    是否可以在 Java 应用程序中运行 Apache Pig 作业 而无需分叉外部进程 Pig 和 Hadoop 似乎都是用 Java 编写的 但并不真正提供 Java API 我宁愿在 Java Spring 应用程序中使用这些工具 而不是
  • 打开本机相机后 Ionic 应用程序崩溃 - 错误 20

    我用的是科尔多瓦camera插件开启ionic 4捕捉一些图像 takePicture console log camera takePicture const options CameraOptions quality 100 desti
  • 使用 RXJava 进行缓存处理

    我正在尝试使用 rxJava 实现此工作流程 但我确定我是否误用或做错了事情 用户要求登录 如果登录结果在缓存中可用 则 发出 缓存的登录结果 否则 如果一切成功 则实际执行对 Web 服务的请求并缓存结果 如果发生错误 最多重试 3 次