【问题标题】:Invoking observable from another observable从另一个可观察对象调用可观察对象
【发布时间】:2018-04-06 21:41:55
【问题描述】:

我是 RxJava 框架的新手。我的系统使用令牌身份验证,当我想从 http 请求中获得任何响应时,由于过期时间,我需要刷新我的身份验证令牌。

但是在从一个 observable 调用 subscribe 方法到另一个 observable 后我遇到了问题

主类(第一个可观察对象)

service.getPosts(offset,limit, PreferencesUtils.getAccessTokenKey())
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnNext(response -> {
            if (!response.isSuccessful()) throw new RuntimeException();
        })
        .subscribe(
            feeds -> mView.showNewsFeedItems(feeds.body()),
            error -> {
                Helper.refreshToken();
                service.getPosts(offset,limit,PreferencesUtils.getAccessTokenKey()); 
            }
        );

我的响应不成功,我需要调用refreshToken(),我可以在其中刷新令牌并将其保存到PreferencesUtils

Helper 类(第二个 observable)

service.refreshToken(PreferencesUtils.getAccessTokenKey(), PreferencesUtils.getRefreshTokenKey())
        .subscribeOn(AndroidSchedulers.mainThread())
        .observeOn(Schedulers.newThread())
        .subscribe(


// doesnt proceed this part of code
                response -> {
                    PreferencesUtils.saveAccessToken(response.body().getAccessToken());
                    PreferencesUtils.saveRefreshToken(response.body().getRefreshToken());
                },

                error -> Log.d(TAG, "refresh token exception: " + `error.getMessage())`
//

            );

当我使用调试器时,来自 Helper 类的 Second observable 无法正常工作,它不想继续此服务,并且在订阅时立即完成而没有任何错误(肯定是在等待完成来自主线程的所有操作)。由于订阅方法没有继续(没有将访问令牌保存到首选项)我无法执行我的service.getPosts() 函数。

请帮忙!我将不胜感激!

【问题讨论】:

    标签: java retrofit rx-java


    【解决方案1】:

    与其像那样拆分观察者链,不如使用retryWhen() 运算符来响应失败的令牌。

    Observable.just(Boolean.TRUE)
        .flatMap( ignored -> service
                               .getPosts(offset,limit,
                                          PreferencesUtils.getAccessTokenKey()) )
        .subscribeOn(Schedulers.computation())
        .doOnNext(response -> {
            if (!response.isSuccessful()) throw new TokenException();
        })
        .retryWhen( error -> error.flatMap( f ->
          {
            if ( f instanceof TokenException ) {
              return service.refreshToken(PreferencesUtils.getAccessTokenKey(), PreferencesUtils.getRefreshTokenKey())
                .doOnNext( response -> {
                    PreferencesUtils.saveAccessToken(response.body().getAccessToken());
                    PreferencesUtils.saveRefreshToken(response.body().getRefreshToken());
                });
            }
            return Observable.error(f);
          })
        )
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe( /* do stuff */ );
    

    retryWhen() 运算符接受一个 observable,它将获取上游抛出的任何异常。如果异常是 TokenException,它将尝试通过调用 refreshToken() 返回的 observable 来刷新令牌,然后将结果保存到您的首选项中。

    编辑:使用可以重新订阅而不会出现问题的 observable 启动观察者链。当必须刷新访问令牌时,将使用新令牌调用getPosts()

    【讨论】:

    • 感谢您的回复!这是很好的逻辑,但是在将令牌保存到preferencesUtils 之后,它仍然使用过时的令牌而不是新的令牌。那么我如何使用新的访问令牌重新调用 getPosts 呢?谢谢
    • service.refreshToken 位于其他类中,因此保存到 Preferences 后我无法在 doOnNext 正文中重新调用 getPosts :(
    • 我从一开始就添加了一个 observable,它将使用新凭据正确调用 getPosts()
    • 非常感谢,它有效!我找不到答案的最后一个问题。为什么我在这行代码中出现编译错误 [ .subscribe(feeds -> mView.showNewsFeedItems(feeds.body())); ] 但 IDE 正确理解它并且不显示任何错误。将“提要”转换为“响应”没有帮助。当我创建一个消费者(观察者)时,一切正常,但我得到了过多的方法,如 onError 和 onUnsubscribe。我将非常感谢该错误:找不到符号方法 body()
    • 我唯一的猜测是括号放错了位置。出于明显的原因,我没有测试我的解决方案,但是将括号放在正确的位置是我最喜欢的错误之一。
    猜你喜欢
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 2022-08-19
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多