缓冲事件,在前一组

时间:2015-06-15 09:55:24

标签: android rx-java rx-android

我在Android上,我创建了一个Observable触摸屏。只要新事件在一秒钟内到来,我想缓冲它们。当从最后一次触摸发射开始经过一秒钟时,我想创建一个所有收集事件的列表并发出它,并开始一个新的集合。

我有两段代码可以使用,但它们要么不太活跃(#1)或不必要的复杂(#2)。他们在这里:

  1. 我使用buffer(Func0<? extends Observable<? extends TClosing>> bufferClosingSelector)重载 - 当返回的选择器发出一个项目时,它意味着从最后一个源发射开始经过了第二个,并且可以发出缓冲区。
  2. 选择器函数返回的ObserbablePublishSubject,以便我可以决定何时向其推送排放。
  3. 存在Runnable任务,将新排放推向最终主题。此任务被安排(通过Android处理程序)在当前处理的源触发发射发生后运行一秒。如果在一秒钟之后发生新触发的新源发射,则该任务将被取消,并且在一秒钟后再次安排新的任务。
  4. 以下是相关的Android代码:

        final PublishSubject<MotionEvent> touchPublishSubject = PublishSubject.create();
    
        final ViewGroup viewGroup = (ViewGroup) findViewById(android.R.id.content);
        viewGroup.setOnTouchListener(new View.OnTouchListener() {
    
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                touchPublishSubject.onNext(event);
    
                return true;
            }
        });
    
        final PublishSubject<Object> windowClosePublishSubject = PublishSubject.create();
        final Handler handler = new Handler(Looper.getMainLooper());
        final Runnable r = new Runnable() {
    
            @Override
            public void run() {
                Log.d(TAG, "will emit closing item");
                windowClosePublishSubject.onNext("now!");
            }
        };
    
        ViewObservable
                .bindView(viewGroup, touchPublishSubject)
                .filter(new Func1<MotionEvent, Boolean>() {
    
                    @Override
                    public Boolean call(MotionEvent motionEvent) {
                        return motionEvent.getAction() == MotionEvent.ACTION_DOWN;
                    }
                })
                .doOnNext(new Action1<MotionEvent>() {
    
                    @Override
                    public void call(MotionEvent motionEvent) {
                        // restart the timer
                        Log.d(TAG, "cancelling closing");
                        handler.removeCallbacks(r);
                        Log.d(TAG, "scheduling closing");
                        handler.postDelayed(r, 1000L);
    
                        // show the touch
                        Log.d(TAG, motionEvent.toString());
                    }
                })
                .buffer(new Func0<Observable<?>>() {
    
                    @Override
                    public Observable<?> call() {
                        Log.d(TAG, "creating buffer closing selector");
                        return windowClosePublishSubject
                                .doOnNext(new Action1<Object>() {
    
                                    @Override
                                    public void call(Object o) {
                                        Log.d(TAG, "emitting closing item '" + o + "'");
                                    }
                                });
                    }
                })
                .subscribe(new Action1<List<MotionEvent>>() {
    
                    @Override
                    public void call(List<MotionEvent> motionEvents) {
                        // show number of touch downs
                        Log.d(TAG, "got " + motionEvents.size() + " touch downs");
                    }
                });
    

    我不喜欢Handler的使用以及此解决方案中的所有内容,所以我进一步了解。

    第二个片段(touchPublishSubject和触控侦听器完全相同):

    1. 我重复使用触摸向下生成touchPublishSubject作为关闭可观察的窗口,首先以1秒的超时时间将其展开
    2. 显然,当在Scheduler.computation()上进行去抖动时,它会将观察移动到同一个调度程序,我需要使用observeOn(AndroidSchedulers.mainThread()) - 我觉得嵌套Observable&#有点奇怪39; s调度程序,只关闭缓冲区窗口, 促进整个链条也在其调度程序中发生
    3. 代码:

          final PublishSubject<MotionEvent> touchPublishSubject = PublishSubject.create();
      
          final ViewGroup viewGroup = (ViewGroup) findViewById(android.R.id.content);
          viewGroup.setOnTouchListener(new View.OnTouchListener() {
      
              @Override
              public boolean onTouch(View v, MotionEvent event) {
                  touchPublishSubject.onNext(event);
      
                  return true;
              }
          });
      
          ViewObservable
                  .bindView(viewGroup, touchPublishSubject)
                  .filter(new Func1<MotionEvent, Boolean>() {
      
                      @Override
                      public Boolean call(MotionEvent motionEvent) {
                          return motionEvent.getAction() == MotionEvent.ACTION_DOWN;
                      }
                  })
                  .doOnNext(new Action1<MotionEvent>() {
      
                      @Override
                      public void call(MotionEvent motionEvent) {
                          // show the touch
                          Log.d(TAG, motionEvent.toString());
                      }
                  })
                  .buffer(new Func0<Observable<?>>() {
      
                      @Override
                      public Observable<?> call() {
                          Log.d(TAG, "creating buffer closing selector");
                          return touchPublishSubject
                                  .debounce(1L, TimeUnit.SECONDS)
                                  .doOnNext(new Action1<Object>() {
      
                                      @Override
                                      public void call(Object o) {
                                          Log.d(TAG, "emitting closing item '" + o + "'");
                                      }
                                  });
                      }
                  })
                  .observeOn(AndroidSchedulers.mainThread())
                  .subscribe(new Action1<List<MotionEvent>>() {
      
                      @Override
                      public void call(List<MotionEvent> motionEvents) {
                          // show number of touch downs
                          Log.d(TAG, "got " + motionEvents.size() + " touch downs");
                      }
                  });
      

      此代码有效,我比第一个更喜欢它,感觉更像是应该使用Rx。但它很复杂,因为嵌套Observable和获得它所需的大脑体操。是否有一个buffer重载我没有自动执行相同操作(即在最后一次发射后1秒钟关闭其窗口)?

      编辑:其中一条评论让我了解了Ben Christensen的演示文稿,然后我发现了这个:https://blog.kaush.co/2015/01/05/debouncedbuffer-with-rxjava/,它链接到了一些问题的实现。看起来像一个非常常见的要求,为此有一个内置的运算符会很好。无论如何,我会考虑在这些其他来源中提出的解决方案,并且这里是针对此类问题的正典。

0 个答案:

没有答案