【问题标题】:Rx and Retrofit: Changing ServiceApi request parameter in request loop started by repeatwhen or repeatuntillRx 和改造:在repeatwhen 或repeatuntill 启动的请求循环中更改ServiceApi 请求参数
【发布时间】:2016-12-12 10:34:28
【问题描述】:

我正在为我的应用程序使用改造和 RxJava。 我正在执行一个请求,该请求将每 1 秒访问一次服务器。为此,我使用请求参数创建改造服务 API,并订阅返回的 observable 并使用 repeatWhen。

问题是,每次请求被命中时,我都想更改随请求发送的请求参数(基本上必须使其动态)。我怎样才能做到这一点?

例如用例:sendLocation Api 每 10 秒向服务器发送当前位置。如何使用改造和 RxJava 实现这一目标

【问题讨论】:

    标签: android rx-java retrofit2


    【解决方案1】:

    如果您添加延迟,@TassosBassoukos 的答案有效。具体来说,这是一个使用 github API 的完整示例,该示例在两个用户之间交替调用。确保不要让它运行太久——

    public interface GitHubService {
        @GET("/users/{user}/repos")
        Observable<String> getRepo(@Path("user") String user);
    }
    
    static String[] users = {"octocat", "square"};
    static int i = 0;
    
    static String getUser() {
        return users[i++ % 2];
     }
    
    public void RxGitRepo() {
        OkHttpClient client = new OkHttpClient();
    
        Retrofit retrofit = new Retrofit.Builder()
          .client(client)
          .baseUrl("https://api.github.com")
          .addConverterFactory(ScalarsConverterFactory.create())
          .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
          .build();
    
       GitHubService gitHubService = retrofit.create(GitHubService.class);
       Observable
          .defer(() -> Observable.just(getUser()))
          .flatMap(user -> gitHubService.getRepo(user))
          .repeatWhen(done -> done.delay(2, TimeUnit.SECONDS))
          .subscribeOn(Schedulers.io())
          .subscribe(System.out::println);
    }
    

    对于您的用例,您可以在该位置上设置您的 observable 并使用它来触发更新,而不是每 10 秒轮询一次位置。使用android-reactiveLocation 之类的库,您可以获得流位置的Observable。类似于以下未经测试的代码的内容 -

    LocationRequest request = LocationRequest.create() 
                                 .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                                 .setInterval(10000);
    
    ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(context);
    Subscription subscription = locationProvider.getUpdatedLocation(request)
        .sample(10, TimeUnits.SECONDS)
        .flatMap(/* your retrofit call based on the observed location */)  
        .subscribe(/* subsciber for retrofit call results */);
    

    【讨论】:

    • 感谢 iagreen。想要一些通用的东西,例如明天而不是位置,我想每隔 2 秒在请求参数中向服务器发送一些文本数据,并且文本数据在不断变化,所以我们如何实现这一点。我的理解是我们必须通过提供请求参数来创建一个改造请求,然后订阅 Service 返回的那个 observable 然后播放它。所以当我将它放入循环时,我如何在下一个滴答声中更改请求参数
    • 我明白您在说什么,但您正在流之外获取其他数据(位置、更改的文本等)。我仍然会将更改的事件包装在一个 observable 中并让它驱动服务器请求——这样我们需要发送的数据自然会以流的形式出现。这对我来说似乎更自然,但请参阅编辑以获取更通用的示例来说明您如何尝试这样做。
    • 我所做的与您提供的第一个示例完全相同,并且有效。谢谢您
    【解决方案2】:

    这个怎么样?

        AtomicInteger requestParam = new AtomicInteger();
    
        apiCall.request(requestParam)
                .doOnNext(response -> requestParam.set(response.getRequestParam()))
                .repeatWhen(objectObservable -> objectObservable
                        .delay(1, TimeUnit.SECONDS)
                        .flatMap(o -> Observable.just(requestParam.get())
                        .takeWhile(integer -> /* condition */ )));
    

    【讨论】:

      【解决方案3】:

      使用这样的东西:

      Observable
      .defer(() -> Observable.just(getLocation))
      .flatMap(location -> doNetworkCall(location))
      .repeatWhen(...)
      

      【讨论】:

        猜你喜欢
        • 2018-12-09
        • 2022-10-06
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-05
        • 1970-01-01
        • 2020-06-14
        相关资源
        最近更新 更多