节流方法调用 RxJava

Throttle method call RxJava

我想使用 RxJava 来限制我从 android.accessibilityservice.AccessibilityService 获得的 AccessibilityEvent 的数量,特别是 TYPE_VIEW_TEXT_CHANGED event.

每当用户在 EditText 小部件中键入任何内容时,它都会被触发。但是我尝试使用 debouncethrottleLastthrottleFirst 甚至 buffer。但是,如果我还没有我想要发出的所有事件,我不确定我应该如何使用它们。

public class AccessibilityService extends android.accessibilityservice.AccessibilityService {

    @Inject
    AccessibilityServiceController accessibilityServiceController;

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        Timber.d("AccessibilityEvent was received: " + event.toString());
        //Throttle so I only get the last event in XXX milliseconds.
        accessibilityServiceController.evaluateEvent(event);
    }

    @Override
    public void onInterrupt() {
        Timber.e("Service was interrupted! ");
    }
} 

我想要在这个 EditText 小部件上使用类似于 debounce 的东西 Kaushik Gopal's DebounceSearchEmitterFragment.java

所以我的输出可以是:

[这是]

[这是一个]

[这是一个测试]

而不是:

[t]

[次]

[你]

[这个]

...

提前致谢!

我会做以下事情:

  • 创建一个设置 "accessibility listener"
  • 的可观察对象
  • 此侦听器可以启动 RxJava 事件流
  • 订阅流,并让服务控制器在适当的时间评估事件

重新设计某些东西以使其具有反应性的关键是确保代码中的所有内容都成为某种触发器。如果您需要来自流的一些逻辑,那么回调不会做太多事情。

下面是一个例子:

AccessibilityServiceController accessibilityServiceController;
Action1<AccessibilityEvent> accessibilityEventListener;

AccessibilityService() {
    accessibilityServiceController = new AccessibilityServiceController();
    Observable.create(new Observable.OnSubscribe<AccessibilityEvent>() {
        @Override
        public void call(final Subscriber<? super AccessibilityEvent> subscriber) {
            accessibilityEventListener = new Action1<AccessibilityEvent>() {
                @Override
                public void call(AccessibilityEvent accessibilityEvent) {
                    subscriber.onNext(accessibilityEvent);
                }
            };
        }
    })
    .debounce(500, TimeUnit.MILLISECONDS) // <-----
    .subscribe(new Action1<AccessibilityEvent>() {
        @Override
        public void call(AccessibilityEvent accessibilityEvent) {
            accessibilityServiceController.evaluateEvent(accessibilityEvent);
        }
    });

}

private void setAccessibilityEventListener(Action1<AccessibilityEvent> listener) {
    accessibilityEventListener = listener;
}

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    // This will be throttled every 500 Milliseconds
    accessibilityEventListener.call(event);
}

你可能不想把这些东西放在构造函数中,但你明白了。 Observable 构建到侦听器 中。我还建议保留对 Subscription 的引用,因为取消订阅以防止内存泄漏很重要!

好的。

我发现有一个 PublishSubject/Subject.

在创建 Observable 之后,我基本上可以 post 到 onNext 作为某种 setter。

public class AccessibilityService extends android.accessibilityservice.AccessibilityService {
    private final PublishSubject<AccessibilityEvent> accessibilityEventPublishSubject = PublishSubject.create();

    public AccessibilityServiceControllerImpl() {
        accessibilityEventPublishSubject
                .debounce(400, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<AccessibilityEvent>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(AccessibilityEvent accessibilityEvent) {
                        Log.d(TAG, accessibilityEvent.toString());
                    }
                });
    }

    @Override
    public void evaluateEvent(final AccessibilityEvent accessibilityEvent) {
        int type = accessibilityEvent.getEventType();
        switch (type) {
            case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
                Timber.d("Event received in controller: " + accessibilityEvent.toString());
                accessibilityEventPublishSubject.onNext(accessibilityEvent);
                break;
            default:
                break;
        }
    }
}

这就是这个问题的答案。但是我面临着空对象,因为它们被 android.accessibilityservice.AccessibilityService 中的 executeMessage 回收。

@Override
public void executeMessage(Message message) {
    switch (message.what) {
        case DO_ON_ACCESSIBILITY_EVENT: {
            AccessibilityEvent event = (AccessibilityEvent) message.obj;
            if (event != null) {
                AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event);
                mCallback.onAccessibilityEvent(event);
                try {
                    //EVENT IS RECYCLED BEFORE THE ONNEXT IS CALLED IN MY PUBLISHSUBJECT
                    event.recycle();
                } catch (IllegalStateException ise) {
                }
            }
        } return;
... bla bla

但我想这里值得再问一个问题。