2012-04-18 8 views
18

Ich verwende den folgenden Code-Suche durchzuführen, wenn Benutzer in einem EditText:Wie vermeidet man mehrere Trigger auf EditText, während der Benutzer tippt?

EditText queryView = (EditText) findViewById(R.id.querybox); 
queryView.addTextChangedListener(new TextWatcher() { 
    @Override 
    public void afterTextChanged(Editable s) { 
    triggerSearch(s.toString()); 
    } 
    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
    } 
    @Override 
    public void onTextChanged(CharSequence s, int start, int before, int count) { 
    } 
}); 

Dies ist jedoch mehrfach ausgelöst, wenn der Benutzer ein Wort ist die Eingabe. Das heißt, wenn der Benutzer "Hallo" tippt, wird dieser Code 5 Mal mit Werten ausgelöst ("h", "he", "hel", "hell", "hallo"). Normalerweise wäre das in Ordnung, aber die ausgelöste Suche ist teuer und ich möchte keine Ressourcen für Zwischensuchen verschwenden, die keinen großen Nutzen haben. Was ich will, ist entweder ein Listener, der nur einen gewissen Schwellenwert auslöst, nachdem der Benutzer anfängt zu tippen, oder eine Art Framework, das im Listener wartet, bevor er triggerSearch aufruft, und wenn vor dieser Wartezeit ein anderes Ereignis ausgelöst wird, bricht es sich ab.

Antwort

45

Da keine geeignete Ereignisschnittstelle finden konnten, haben versucht, eine verzögerte Suche auszulösen. Der Code ist eigentlich ziemlich einfach und robust.

private final int TRIGGER_SERACH = 1; 
// Where did 1000 come from? It's arbitrary, since I can't find average android typing speed. 
private final long SEARCH_TRIGGER_DELAY_IN_MS = 1000; 

    private Handler handler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     if (msg.what == TRIGGER_SERACH) { 
     triggerSearch(); 
     } 
    } 
    }; 

queryView.addTextChangedListener(new TextWatcher() { 

    @Override 
    public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { 

    } 

    @Override 
    public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { 

    } 

    @Override 
    public void afterTextChanged(Editable s) { 
    handler.removeMessages(TRIGGER_SERACH); 
    handler.sendEmptyMessageDelayed(TRIGGER_SERACH, SEARCH_TRIGGER_DELAY_IN_MS); 
    }); 
+2

Diese Handler-Klasse sollte statisch sein oder Lecks auftreten. – Choletski

+0

@Choletski bitte erläutern, wie Lecks auftreten können und statische Aufladung wird dies verhindern? – jitenagarwal19

+0

@ jitenagarwal19 ein statischer Handler würde keinen Verweis auf die umschließende Klasse behalten – andrei

4

Eine Lösung wäre, Ihre getriggerte Suche nicht sofort auszuführen, sondern nach einem Intervall von sagen wir 100ms, seit die Methode onTextChanged aufgerufen wird. Setzen Sie dieses Intervall außerdem jedes Mal zurück, wenn Text eingegeben wird.

Auf diese Weise wird die ausgelöste Suche nicht aufgerufen, während der Benutzer tippt.

3

In den Hörer vor dem Anruf warten triggerSearch; Testen Sie die Länge von Editable s.

if(s.length() > THRESHOLD)

+0

Wie bestimmen Sie einen geeigneten Schwellenwert? Dies funktioniert auch nicht, wenn der Benutzer ein langes Wort eingibt, das aus vielen Buchstaben besteht, die länger als der Schwellenwert sind. – slayton

+0

Wie Sie bemerkt haben, hat der Benutzer nicht angegeben, welche Suche er auslöst. Ohne Zusammenhang spekuliere ich nicht, dass etwas zu begrenzt oder übertrieben ist. Hast du in Betracht gezogen, wenn jemand weniger als 10 Buchstaben pro Sekunde tippt, wo "h", "he", "hel", "hell", "hallo" heißen, weil deine Schwelle zu kurz ist? Beide Antworten sind gültig, bitte kennzeichnen Sie meine Antwort, wenn Sie sich immer noch beleidigt fühlen und glauben, dass eine Überprüfung der Community erforderlich ist. – Sam

+0

+1 da es immer noch ein cleverster Ansatz für einige Situationen ist – aProgrammer

0

Wenn Sie die Suche auf jeder Taste gedrückt, um nicht auslösen wollen, dann müssen Sie wissen, wann der Benutzer erfolgt. Ich würde komplexe Ideen vermeiden, die versuchen herauszufinden, wann der Benutzer mit dem Tippen fertig ist. Dies führt dazu, dass der Benutzer verwirrt ist, wenn die Suche stattfindet.

Einfache Antwort dann ist eine Schaltfläche "fertig" und wenden Sie einen onClickListener auf die Schaltfläche und führen Sie Ihre Suche dort.

einfachste Code: in xml

<Button 
android:onClick="onDoneClicked" 
... the rest of your button layout 
/> 

in java:

@Override 
public void onDoneClicked(View view){ 
EditText queryView = (EditText) findViewById(R.id.querybox); 
triggerSearch(queryView.toString()); 
} 
Verwandte Themen