如何执行" RXJava 2队列作业"直到价值变化?

时间:2018-01-09 13:00:44

标签: android sockets rx-java2

我在我的Android应用程序中使用RXJava2,我有一个奇怪的场景。 我想执行未知数量的作业(由用户确定),但我希望它们仅在某个值发生变化后才启动。

我的具体要求是使用Socket进行服务器通信, 流程如下:

  1. 用户请求一些数据 - 通过向套接字发送数据并等待响应来检索数据。
  2. 与服务器通信的模块应该打开Socket连接,并且只有在建立连接后,它才可以获取所请求的数据。
  3. 当Socket尝试连接时,用户可能会请求更多数据。
  4. 成功建立连接后,模块应该在连接过程正在进行时执行用户发送的所有请求。
  5. 模块还应该发布发送到套接字的每个数据的结果。
  6. 如何使用RXJava2实现这一目标?

    先谢谢。

2 个答案:

答案 0 :(得分:3)

您可以使用UnicastSubject作为队列部分并执行一些flatMap - 一旦建立连接就ping:

UnicastSubject<String> userRequests = new UnicastSubject.create();

Single.fromCallable(() -> new Socket("server", port))
  .subscribeOn(Schedulers.io())
  .flatMapObservable(socket -> {

      InputStream in = socket.getInputStream();
      OutputStream out = socket.getOutputStream();
      byte[] responseBuffer = new byte[4096];

      return userRequests
         .observeOn(Schedulers.io())
         .map(request -> {

             out.write(request.getBytes());

             int n = in.read(responseBuffer);
             if (n >= 0) {
                 return new String(responseBuffer, 0, n);
             }

             throw new IOException("Socket closed while waiting for response");
         })
         .doFinally(() -> socket.close());
  });

由于您正在处理Socket级别,因此您有责任确定要写入的请求的正确编码以及要读取的响应的正确解码(即,响应的长度(以字节为单位)特定的要求)。

答案 1 :(得分:0)

我相信你需要FlowableTransformers.valve()RxJava2Extensions

它应该像这样工作

    PublishSubject<String> jobs = PublishSubject.create().toSerialized();

    BehaviorSubject<Boolean> isConnected = BehaviorSubject.createDefault(false);

    CompositeDisposable disposables = new CompositeDisposable();

    public void connect() {
        disposables.add(socketService.subscribe((success) -> {
            isConnected = true;
        }));
    }

    public void addJob(String job) {
        jobs.onNext(job);
    }

    public void executeQueuedTasks() {
       disposables.add(jobs
          .toFlowable(BackpressureStrategy.BUFFER)
          .compose(FlowableTransformers.valve(isConnected))
          .subscribeWith(new DisposableObserver<>() {
              ...
          })
       );
    }

    public void destroy() {
        disposables.clear();
    }
}

但上面的UnicastSubject样本更有可能发挥作用,我把它写在了我的头顶。