1

In a AutoCompleteTextView I want to show the auto complete list after there is a pause of 1 sec by user in typing. I tried using handler

handler.postDelayed( new Runnable() {

            @Override
            public void run() {

                // TODO Auto-generated method stub
                if ( text.length() >= 3 ) {
                    // do something                     

                } else if ( text.length() == 0 ) {
                    // do something

                }
            }

        }, 1000 );

This code is a part of onTextChanged. So what it is happening is whenever there is a text change at that moment postDelayed is called and inside code will be called after a second. So how can I prevent that so the inner code is only called when there is a puase of 1 sec by user in typing.

e.g: If I type Ind (pause of 1 sec) then inner code execute should happen. But I type India then inner code should not execute for Ind, Indi, India. Need your suggestions.

4

4 に答える 4

2

タイムスタンプを保持する2つの静的変数を作成します。
lastTimeStampそしてcurrentTimeStamp、あなたはこのようなことをすることができます:

        @Override
        public void run() {
            if (currentTimeStamp - lastTimeStamp > 1000) {
               // TODO Auto-generated method stub
               if ( text.length() >= 3 ) {
                  // do something                     

               } else if ( text.length() == 0 ) {
                     // do something

               }
            }
        }

新しいアプローチ:

onTextChangedメソッドの先頭で、現在のTimeStampをクラス変数に入れます。
その後、onTextChangedでAsyncTaskを作成します。これは、 Thread.sleep(1000)doInBackgroundメソッドで実行しているだけです。
次に、postExcuteメソッドでifステートメントを作成し、クラス変数のTimeStampと現在のTimeStampの違いが1000より大きいかどうかを確認し、ハンドラーをポストします。

于 2013-02-25T12:30:55.653 に答える
1

私はちょうど同じ問題に立っていました。
私は Google の Geocode 提案 API onTextChanged() を呼び出しており、それが多くの問題を引き起こしました。ユーザーが入力すると大量の API 要求が発生しますが、そのほとんどは不要であり、API を使い果たし (費用がかかります)、ユーザーがアプリから受け取るエクスペリエンスが低下します。

ここで解決策を検討しましたが、最終的にはどれも好きではありませんでした。それらは汚れているか、ハックのように見えました。
ビューの現在の値を取得したり (再度)、システム時間を確認したりするために、UI をさらに呼び出したくありませんでした。

元の質問は実際にはすでに問題を解決しています。ユーザーが入力したときに複数のランナブルがアクティブになるだけです。
したがって、問題は次のとおりです。「問題が発生する前に、匿名のランナブルを削除するにはどうすればよいですか?」

元のアプローチ (匿名ランナブルを使用した遅延呼び出し) を使用する必要があるだけで、onTextChanged 関数が呼び出されるたびに、以前のランナブルを削除します。
また、コードを拡張して、値が実際に変更されたかどうかを確認することもできます (グローバルな以前の値の文字列を使用するなど)。これにより、ユーザーが文字を入力して再度削除した場合にランナブルが強制終了されなくなります。

1. Handler を onTextChanged 内で作成するのではなく、クラスの変数にします。
2. onTextChanged の開始時に、ランナブルをハンドラーから削除します。

完全に機能する例を次に示します。

    Handler onchangeHandler =  new Handler();
    String last_onTextChanged=""; // may speed up some cases of user input, can be removed
    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
    {
        final String value = charSequence.toString();
        if (value.length() < 3) {autoCompleteAdapter.clear();return;} // threshold of 3 chars

        if (!last_onTextChanged.equals(value))
            onchangeHandler.removeCallbacksAndMessages(null);
        else
            return;
    last_onTextChanged=value;
    onchangeHandler.postDelayed(new Runnable()
    {
        @Override
        public void run()
        {
            // RUN CODE HERE, fill your autoCompleteAdapter etc.
        }
    },800);

}
于 2014-04-05T16:07:45.770 に答える
0

2 つのオプションがあります。

  1. 次のタスクを実行するときは、Timer を使用して前のタスクで cancel() を呼び出します。

  2. Runnable を拡張し、このオートコンプリートの文字列を渡します。この文字列が表示されている現在の文字列と等しくない場合 (つまり、ユーザーが文字列を変更したことを意味します)、オートコンプリートを表示しないでください。

コード例:

abstract class MyRunnable {
    private String str;

    public MyRunnable(String str) {
        this.str = str;
    }
}


...

handler.postDelayed(new MyRunnable(currentViewStr) {

    @Override
    public void run() {
        if (currentViewStr.equals(str)) {
            // show autocompletion
        }
    }
}, 1000);
于 2013-02-25T12:55:55.853 に答える
0

Runnableメッセージキューの前のメッセージを最初にキャンセルすることもできますonTextChanged()

于 2013-02-25T13:23:07.243 に答える