ユーザー入力の定期的な処理を実装するにはどうすればよいですか?

ヘクトール

私の現在のAndroidアプリケーションでは、ユーザーはコンテンツをリモートで検索できます。

たとえば、ユーザーにはEditText、検索文字列を受け入れ、入力されたテキストに一致する結果を返すリモートAPI呼び出しをトリガーするが表示されます。

最悪の場合は、を追加してTextWatcher、呼び出されるたびにAPI呼び出しをトリガーするだけonTextChangedです。これは、最初のAPI呼び出しを行う前に、ユーザーに検索するために少なくともN文字を入力するように強制することで改善できます。

「完璧な」ソリューションには、次の機能があります。-

ユーザーが検索文字列の入力を開始すると

定期的に(Mミリ秒ごとに)入力された文字列全体を消費します。期間が終了し、現在のユーザー入力が前のユーザー入力と異なるたびにAPI呼び出しをトリガーします。

[入力したテキストの長さに関連する動的タイムアウトを設定することはできますか?たとえば、テキストが「短い」間、API応答サイズは大きくなり、戻りと解析に時間がかかります。検索テキストが長くなると、API応答サイズは「機内」および解析時間とともに減少します]

ユーザーがEditTextフィールドへの入力を再開すると、テキストの定期的な消費が再開されます。

ユーザーがENTERキーを押すたびに、「最終」API呼び出しがトリガーされ、EditTextフィールドへのユーザー入力の監視が停止されます。

API呼び出しがトリガーされる前にユーザーが入力する必要のあるテキストの最小長を設定しますが、ユーザーが「短い」テキスト文字列を検索したいときにできるように、この最小長をオーバーライドするタイムアウト値と組み合わせます。

RxJavaやRxBindingsは上記の要件をサポートできると確信していますが、これまでのところ、実行可能なソリューションを実現できていません。

私の試みは含まれています

private PublishSubject<String> publishSubject;

  publishSubject = PublishSubject.create();
        publishSubject.filter(text -> text.length() > 2)
                .debounce(300, TimeUnit.MILLISECONDS)
                .toFlowable(BackpressureStrategy.LATEST)
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(final String s) throws Exception {
                        Log.d(TAG, "accept() called with: s = [" + s + "]");
                    }
                });


       mEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {

            }

            @Override
            public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
                publishSubject.onNext(s.toString());
            }

            @Override
            public void afterTextChanged(final Editable s) {

            }
        });

そしてこれはRxBindingで

 RxTextView.textChanges(mEditText)
                .debounce(500, TimeUnit.MILLISECONDS)
                .subscribe(new Consumer<CharSequence>(){
                    @Override
                    public void accept(final CharSequence charSequence) throws Exception {
                        Log.d(TAG, "accept() called with: charSequence = [" + charSequence + "]");
                    }
                });

どちらも、入力されたテキストの長さとタイムアウト値を組み合わせた条件付きフィルターを提供しません。

また、debounceをthrottleLastに置き換え、どちらも必要なソリューションを提供しなかったサンプルを作成しました。

必要な機能を実現することはできますか?

動的タイムアウト

許容できるソリューションは、次の3つのシナリオに対応します。

私)。ユーザーが「P」で始まる任意の単語を検索したい

ii)。ユーザーが「Pneumo」で始まる単語を検索したい

iii)。ユーザーが「ニューモノウルトラマイクロスコピックシリコボルカノコニオーシス」という単語を検索したい

3つのシナリオすべてで、ユーザーが文字「P」を入力するとすぐに、進行状況スピナーが表示されます(ただし、この時点ではAPI呼び出しは実行されません)。レスポンシブUI内でユーザーに検索フィードバックを提供する必要性と、ネットワークを介して「無駄な」API呼び出しを行う必要性のバランスを取りたいと思います。

ユーザーが検索テキストを入力してから「完了」(または「Enter」)キーをクリックすることに頼ることができれば、最後のAPI呼び出しをすぐに開始できます。

シナリオ1

ユーザーが入力したテキストの長さが短いため(たとえば、1文字の長さ)、タイムアウト値は最大値になります。これにより、ユーザーは追加の文字を入力でき、「無駄なAPI呼び出し」を節約できます。

ユーザーが文字「P」だけを検索したいので、最大タイムアウトが経過したら、API呼び出しを実行して結果を表示します。このシナリオでは、動的タイムアウトが期限切れになるのを待ってから、ラージAPI応答が返され、表示されるのを待つ必要があるため、ユーザーエクスペリエンスが最悪になります。中間検索結果は表示されません。

シナリオ2

このシナリオは、ユーザーが6文字すべてを「すばやく」入力した場合にユーザーが何を検索するのか(または検索文字列の最終的な長さ)がわからないため、シナリオ1を組み合わせたものです。1つのAPI呼び出しを実行できますが、6文字の入力が遅くなります。文字を使用すると、無駄なAPI呼び出しを実行する可能性が高くなります。

このシナリオでは、動的タイムアウトが期限切れになるのを待つ必要があるため、ユーザーエクスペリエンスが向上しますが、中間検索結果が表示される可能性があります。API応答は、シナリオ1よりも小さくなります。

シナリオ3

このシナリオは、シナリオ1と2を組み合わせたものです。ユーザーが45文字すべてを「すばやく」入力した場合、ユーザーが何を検索するのか(または検索文字列の最終的な長さ)がわからないため、1つのAPI呼び出しを実行できます(多分!)。 45文字の入力が遅いと、無駄なAPI呼び出しを実行する可能性が高くなります。

私は、希望するソリューションを提供するテクノロジーに縛られていません。Rxは私がこれまでに特定した最良のアプローチだと思います。

yosriz

このようなものはうまくいくはずです(実際には試していませんでした)

 Single<String> firstTypeOnlyStream = RxTextView.textChanges(mEditText)
            .skipInitialValue()
            .map(CharSequence::toString)
            .firstOrError();

    Observable<CharSequence> restartTypingStream = RxTextView.textChanges(mEditText)
            .filter(charSequence -> charSequence.length() == 0);

    Single<String> latestTextStream = RxTextView.textChanges(mEditText)
            .map(CharSequence::toString)
            .firstOrError();

    Observable<TextViewEditorActionEvent> enterStream =
            RxTextView.editorActionEvents(mEditText, actionEvent -> actionEvent.actionId() == EditorInfo.IME_ACTION_DONE);

    firstTypeOnlyStream
            .flatMapObservable(__ ->
                    latestTextStream
                            .toObservable()
                            .doOnNext(text -> nextDelay = delayByLength(text.length()))
                            .repeatWhen(objectObservable -> objectObservable
                                    .flatMap(o -> Observable.timer(nextDelay, TimeUnit.MILLISECONDS)))
                            .distinctUntilChanged()
                            .flatMap(text -> {
                                if (text.length() > MINIMUM_TEXT_LENGTH) {
                                    return apiRequest(text);
                                } else {
                                    return Observable.empty();
                                }
                            })
            )
            .takeUntil(restartTypingStream)
            .repeat()
            .takeUntil(enterStream)
            .mergeWith(enterStream.flatMap(__ ->
                    latestTextStream.flatMapObservable(this::apiRequest)
            ))
            .subscribe(requestResult -> {
                //do your thing with each request result
            });

アイデアは、X回ごとにサンプリングするという要件に基づいて、テキスト変更イベント自体ではなく、サンプリングに基づいてストリームを構築することです。

ここで私が行った方法は、1つのストリームを作成することです(firstTypeOnlyStreamイベントの最初のトリガー(ユーザーがテキストを初めて入力するとき)の場合、このストリームは、ユーザーの最初の入力で処理ストリーム全体を開始します。トリガーが到着したら、基本的に定期的に編集テキストをサンプリングしますlatestTextStream。これlatestTextStreamは実際には時間の経過に伴うストリームではなく、RxBindingEditTextInitialValueObservableプロパティを使用した現在の状態のサンプリングです(サブスクリプションで現在のテキストを出力するだけですEditText)。言い換えれば、これはサブスクリプションで現在のテキストを取得するための素晴らしい方法であり、
Observable.fromCallable(() -> mEditText.getText().toString());
次と同等です。次に、動的タイムアウト/遅延の場合nextDelay、テキストの長さに基づいて更新repeatWhen、タイマーを使用して目的の時間を待機します。distinctUntilChanged、テキストの長さに基づいて必要なサンプリングを提供する必要があります。さらに、テキストに基づいてリクエストを送信します(十分な長さの場合)。

入力による停止-使用はtakeUntilしてenterStreamいる入力にトリガーされると、それはまた、最終的なクエリをトリガします。

起動-ユーザーが '再起動'入力を開始すると-つまり、テキストが空の場合、.takeUntil(restartTypingStream)+repeat()は空の文字列が入力されたときにストリームを停止し、再起動(再サブスクライブ)します。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

2つの配列を反復処理してユーザー入力を出力するにはどうすればよいですか?

分類Dev

不明な数のユーザー文字列を入力するにはどうすればよいですか?

分類Dev

ユーザーに複数の入力を入力させるにはどうすればよいですか?

分類Dev

ユーザーが入力フィールドに数字のみを入力できないようにするにはどうすればよいですか?

分類Dev

sedコマンドに、ユーザーが入力していない入力パラメーターのエスケープ文字を処理させるにはどうすればよいですか?

分類Dev

ユーザーからのコンソール入力を許可しながらNSTimerを実行するにはどうすればよいですか?

分類Dev

Pythonでユーザー入力のループを作成するにはどうすればよいですか?

分類Dev

ユーザーストーリーの受け入れ基準の変更を処理するにはどうすればよいですか?

分類Dev

ユーザー入力なしで文字列のスペルチェックを実行するにはどうすればよいですか?

分類Dev

ユーザーが有効な選択肢を確実に入力できるようにするにはどうすればよいですか?

分類Dev

Pythonでのユーザー入力後の改行を回避するにはどうすればよいですか?

分類Dev

ユーザーがC ++で入力しているときに、ユーザーの入力を確認するにはどうすればよいですか?

分類Dev

これらのユーザー入力を平均するにはどうすればよいですか?

分類Dev

ユーザーの入力をapi.ai(dialogflow)に保存するにはどうすればよいですか?

分類Dev

thymeleafで入力ユーザー名の値を取得するにはどうすればよいですか?

分類Dev

この「LocalProcessingExceptionがユーザーコードによって処理されなかった」を解決するにはどうすればよいですか?

分類Dev

Watson Assistantでユーザー入力に1つの単語しかないかどうかを検出するにはどうすればよいですか?

分類Dev

ユーザーが既存の主キーIDを入力しようとしないようにするにはどうすればよいですか?

分類Dev

ユーザー入力の待機を停止するにはどうすればよいですか?

分類Dev

tkinterラベルのユーザー入力を取得するにはどうすればよいですか?

分類Dev

CasperJSの実行を停止し、ユーザーに値を入力させてから実行を継続するにはどうすればよいですか?

分類Dev

`format_args!`のような複雑なマクロをユーザースペースに実装するにはどうすればよいですか?

分類Dev

nextLine() にユーザーの入力を待機させるにはどうすればよいですか?

分類Dev

入力フィールドに数字のみを入力するようにユーザーを制限するにはどうすればよいですか?

分類Dev

Ionic 3でのアプリ内購入-ユーザー間の支払いを実装するにはどうすればよいですか?

分類Dev

関数を実行し、ユーザー入力を待ってから、別の関数を実行するにはどうすればよいですか?

分類Dev

Spring MVCでユーザーログインを処理するにはどうすればよいですか?

分類Dev

ユーザーが文字(a、b、c、d ..)やその他の文字(<、>、@ <、!...)を入力できないようにするにはどうすればよいですか?

分類Dev

ユーザーが入力に数字を入力できないようにするにはどうすればよいですか?

Related 関連記事

  1. 1

    2つの配列を反復処理してユーザー入力を出力するにはどうすればよいですか?

  2. 2

    不明な数のユーザー文字列を入力するにはどうすればよいですか?

  3. 3

    ユーザーに複数の入力を入力させるにはどうすればよいですか?

  4. 4

    ユーザーが入力フィールドに数字のみを入力できないようにするにはどうすればよいですか?

  5. 5

    sedコマンドに、ユーザーが入力していない入力パラメーターのエスケープ文字を処理させるにはどうすればよいですか?

  6. 6

    ユーザーからのコンソール入力を許可しながらNSTimerを実行するにはどうすればよいですか?

  7. 7

    Pythonでユーザー入力のループを作成するにはどうすればよいですか?

  8. 8

    ユーザーストーリーの受け入れ基準の変更を処理するにはどうすればよいですか?

  9. 9

    ユーザー入力なしで文字列のスペルチェックを実行するにはどうすればよいですか?

  10. 10

    ユーザーが有効な選択肢を確実に入力できるようにするにはどうすればよいですか?

  11. 11

    Pythonでのユーザー入力後の改行を回避するにはどうすればよいですか?

  12. 12

    ユーザーがC ++で入力しているときに、ユーザーの入力を確認するにはどうすればよいですか?

  13. 13

    これらのユーザー入力を平均するにはどうすればよいですか?

  14. 14

    ユーザーの入力をapi.ai(dialogflow)に保存するにはどうすればよいですか?

  15. 15

    thymeleafで入力ユーザー名の値を取得するにはどうすればよいですか?

  16. 16

    この「LocalProcessingExceptionがユーザーコードによって処理されなかった」を解決するにはどうすればよいですか?

  17. 17

    Watson Assistantでユーザー入力に1つの単語しかないかどうかを検出するにはどうすればよいですか?

  18. 18

    ユーザーが既存の主キーIDを入力しようとしないようにするにはどうすればよいですか?

  19. 19

    ユーザー入力の待機を停止するにはどうすればよいですか?

  20. 20

    tkinterラベルのユーザー入力を取得するにはどうすればよいですか?

  21. 21

    CasperJSの実行を停止し、ユーザーに値を入力させてから実行を継続するにはどうすればよいですか?

  22. 22

    `format_args!`のような複雑なマクロをユーザースペースに実装するにはどうすればよいですか?

  23. 23

    nextLine() にユーザーの入力を待機させるにはどうすればよいですか?

  24. 24

    入力フィールドに数字のみを入力するようにユーザーを制限するにはどうすればよいですか?

  25. 25

    Ionic 3でのアプリ内購入-ユーザー間の支払いを実装するにはどうすればよいですか?

  26. 26

    関数を実行し、ユーザー入力を待ってから、別の関数を実行するにはどうすればよいですか?

  27. 27

    Spring MVCでユーザーログインを処理するにはどうすればよいですか?

  28. 28

    ユーザーが文字(a、b、c、d ..)やその他の文字(<、>、@ <、!...)を入力できないようにするにはどうすればよいですか?

  29. 29

    ユーザーが入力に数字を入力できないようにするにはどうすればよいですか?

ホットタグ

アーカイブ