如何只发送Rx和Retrofit的最后一次请求?

时间:2017-02-28 08:12:03

标签: android retrofit rx-java rx-android

我有一个EditText视图和TextWatcher,在onTextChanged方法中,我必须从EditText字段查询服务器的结果。 在我的演示者中,我使用rx,但我需要延迟搜索,直到用户的输入结束。在这一刻,我得到了这个:

service.getData(query)
            .delaySubscription(REQUEST_DELAY_FROM_SERVER, TimeUnit.MILLISECONDS, Schedulers.io())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    data-> {
                        getViewState().showData(data);
                    },
                    error -> {
                        Log.e(this.getClass().getSimpleName(), error.getMessage(), error);
                    }
            );

但是,delaySubscription无法正常工作。它收集所有呼叫,延迟后发送每个呼叫。我必须这样做,好像我曾经使用过handler.postDelayed(),只发送一次请求。

3 个答案:

答案 0 :(得分:7)

编辑2:

RxJava2

中演示者的主食
class Presenter {
    private PublishSubject<String> queryPublishSubject = PublishSubject.create();

    public Presenter() {
        queryPublishSubject
                .debounce(1000, TimeUnit.MILLISECONDS)
                // You might want to skip empty strings
                .filter(new Predicate<CharSequence>() {
                    @Override
                    public boolean test(CharSequence charSequence) {
                        return charSequence.length() > 0;
                    }
                })
                // Switch to IO thread for network call and flatMap text input to API request
                .observeOn(Schedulers.io())
                .flatMap(new Function<CharSequence, Observable<...>() {
                    @Override
                    public Observable<...> apply(final CharSequence charSequence) {
                        return ...; // Call API
                    }
                })
                // Receive and process response on Main thread (if you need to update UI)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(...);
    }

    public void onSearchTextChanged(String query) {
        queryPublishSubject.onNext(query);
    }
}

编辑1:

RxJava 1 中的相同代码:

class Presenter {
    private PublishSubject<String> queryPublishSubject = PublishSubject.crate();

    public Presenter() {
        queryPublishSubject
            .debounce(1000, TimeUnit.MILLISECONDS)
            // You might want to skip empty strings
            .filter(new Func1<CharSequence, Boolean>() {
                @Override
                public Boolean call(CharSequence charSequence) {
                    return charSequence.length() > 0;
                }
            })
            // Switch to IO thread for network call and flatMap text input to API request
            .observeOn(Schedulers.io())
            .flatMap(new Func1<CharSequence, Observable<...>() {
                @Override
                public Observable<...> call(final CharSequence charSequence) {
                    return ... // Call API
                }
            })
            // Receive and process response on Main thread (if you need to update UI)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(...);
    }

    public void onSearchTextChanged(String query) {
        queryPublishSubject.onNext(query);
    } 
}  

初始答案(使用RxBinding和RxJava 1)

正确的答案是使用Debounce,但除此之外还有一些其他技巧可能会有用

textChangeListener = RxTextView
    .textChanges(queryEditText)
    // as far as I know, subscription to textChanges is allowed from Main thread only
    .subscribeOn(AndroidSchedulers.mainThread()) 
    // On subscription Observable emits current text field value. You might not need that
    .skip(1) 
    .debounce(1000, TimeUnit.MILLISECONDS)
    // You might want to skip empty strings
    .filter(new Func1<CharSequence, Boolean>() {
        @Override
        public Boolean call(CharSequence charSequence) {
            return charSequence.length() > 0;
        }
    })
    // Switch to IO thread for network call and flatMap text input to API request
    .observeOn(Schedulers.io())
    .flatMap(new Func1<CharSequence, Observable<...>() {
        @Override
        public Observable<...> call(final CharSequence charSequence) {
            return ... // Call API
        }
    })
    // Receive and process response on Main thread (if you need to update UI)
    .observeOn(AndroidSchedulers.mainThread())

答案 1 :(得分:1)

我有一些类似的地址研究结合RxAndroid可以给出类似的东西:

Sub Macro4()
'
' Macro4 Macro
'

Sheets("Temp").Select
    Workbooks.Open Filename:= _
        "C:\Users\BERAAR1\Desktop\Utilization_matrix\Requests_Weekly.xml"
    Range("A1").Select
    Range(Selection, Selection.End(xlToRight)).Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.Copy
    Windows("test.xlsm").Activate
    Sheets("Temp").Select
    ActiveSheet.Paste
    Windows("Requests_Weekly.xml").Activate
    ActiveWindow.Close
End Sub

debounce运算符将在这种情况下等待observable在发出下一个值之前停止发出100ms。

答案 2 :(得分:0)

请尝试使用去抖动。例如。下面的代码查找TextView中的更改,并在有更改但是去抖动为100毫秒时执行某些操作

{{1}}