android - wearable - wearos app tutorial




So vermeiden Sie einen Toast, wenn bereits ein Toast angezeigt wird (6)

Ich habe mehrere SeekBar und onSeekBarProgressStop() , ich möchte eine Toast Nachricht onSeekBarProgressStop() .

Aber wenn ich auf SeekBar die Aktion schnell durchführe, blockiert der UI-Thread irgendwie und die Toast Nachricht wartet, bis der UI-Thread frei ist.

Jetzt ist es mein Anliegen, die neue Toast Nachricht zu vermeiden, wenn die Toast Nachricht bereits angezeigt wird. Oder ist dies eine Bedingung, anhand derer wir überprüfen, ob der UI-Thread derzeit frei ist, dann zeige ich die Toast Nachricht.

Ich habe es auf beide runOnUIThread() versucht, indem runOnUIThread() und auch einen neuen Handler .


Eine kombinierte Lösung

In meinem Fall musste ich den aktuellen Toast abbrechen, wenn er angezeigt wurde, und einen anderen anzeigen.

Dies sollte das Szenario lösen, in dem der Benutzer nach einem Dienst fragt, während er noch geladen wird oder nicht verfügbar ist. Ich muss einen Toast vorzeigen (möglicherweise anders, wenn der angeforderte Dienst anders ist). Andernfalls werden die Toasts weiterhin angezeigt und es dauert sehr lange, bis sie automatisch ausgeblendet werden.

Im Grunde speichere ich die Instanz, die der Toast erstellt, und der folgende Code gibt an, wie er sicher abgebrochen werden kann

synchronized public void cancel() {
    if(toast == null) {
        Log.d(TAG, "cancel: toast is null (occurs first time only)" );
        return;
    }
    final View view = toast.getView();
    if(view == null){
        Log.d(TAG, "cancel: view is null");
        return;
    }
    if (view.isShown()) {
        toast.cancel();
    }else{
        Log.d(TAG, "cancel: view is already dismissed");
    }
}

Und um es zu benutzen, kann ich mich jetzt nicht mehr darum kümmern, wie in:

if (toastSingleton != null ) {
    toastSingleton.cancel();
    toastSingleton.showToast(messageText);
}else{
    Log.e(TAG, "setMessageText: toastSingleton is null");
}

Der showToast hängt von Ihnen ab, wie er implementiert wird, da ich einen benutzerdefinierten Look für meinen Toast benötigte.


Behalten Sie den Überblick über das letzte Mal, als Sie den Toast gezeigt haben, und machen Sie das erneute Anzeigen zu einem No-Op, wenn es in ein Intervall fällt.

public class RepeatSafeToast {

    private static final int DURATION = 4000;

    private static final Map<Object, Long> lastShown = new HashMap<Object, Long>();

    private static boolean isRecent(Object obj) {
        Long last = lastShown.get(obj);
        if (last == null) {
            return false;
        }
        long now = System.currentTimeMillis();
        if (last + DURATION < now) {
            return false;
        }
        return true;
    }

    public static synchronized void show(Context context, int resId) {
        if (isRecent(resId)) {
            return;
        }
        Toast.makeText(context, resId, Toast.LENGTH_LONG).show();
        lastShown.put(resId, System.currentTimeMillis());
    }

    public static synchronized void show(Context context, String msg) {
        if (isRecent(msg)) {
            return;
        }
        Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
        lastShown.put(msg, System.currentTimeMillis());
    }
}

und dann,

RepeatSafeToast.show(this, "Hello, toast.");
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown

Dies ist nicht perfekt, da die Länge von LENGTH_SHORT und LENGTH_LONG undefiniert ist, aber in der Praxis gut funktioniert. Dies hat gegenüber anderen Lösungen den Vorteil, dass Sie sich nicht am Toast-Objekt festhalten müssen und die Aufrufsyntax knapp bleibt.


Die erweiterte Funktion aus dem obigen Thread, die nur Toast anzeigt, wenn sie nicht mit derselben Textnachricht angezeigt wird:

 public void showSingleToast(){
        try{
            if(!toast.getView().isShown()) {    
                toast.show();
            }
        } catch (Exception exception) {
            exception.printStackTrace();       
            Log.d(TAG,"Toast Exception is "+exception.getLocalizedMessage());
            toast = Toast.makeText(this.getActivity(),   getContext().getString(R.string.no_search_result_fou`enter code here`nd), Toast.LENGTH_SHORT);
            toast.show();
        }

    }

Eine saubere Lösung, die sofort funktioniert. Definieren Sie dies für Ihre Aktivität:

private Toast toast;

/**
 * Use this to prevent multiple Toasts from spamming the UI for a long time.
 */
public void showToast(CharSequence text, int duration)
{
    if (toast == null)
        toast = Toast.makeText(this, text, duration);
    else
        toast.setText(text);
    toast.show();
}

public void showToast(int resId, int duration)
{
    showToast(getResources().getText(resId), duration);
}

Ich habe eine Vielzahl von Dingen ausprobiert, um dies zu tun. Zuerst habe ich versucht, cancel() , was für mich keine Auswirkung hatte (siehe auch diese Antwort ).

Mit setDuration(n) bin ich auch nirgendwo setDuration(n) . Es stellte sich heraus, dass getDuration() Wert 0 (wenn der Parameter von makeText() Toast.LENGTH_SHORT ) oder 1 (wenn der Parameter von makeText() Toast.LENGTH_LONG ) enthält.

Schließlich habe ich versucht, zu überprüfen, ob die Toast-Ansicht isShown() . Wenn kein Toast angezeigt wird, ist dies natürlich nicht der Fall, aber in diesem Fall wird ein schwerwiegender Fehler zurückgegeben. Also musste ich versuchen, den Fehler abzufangen. Jetzt gibt isShown() true zurück, wenn ein Toast angezeigt wird. Unter Verwendung von isShown() ich die folgende Methode gefunden:

    /**
     * <strong>public void showAToast (String st)</strong></br>
     * this little method displays a toast on the screen.</br>
     * it checks if a toast is currently visible</br>
     * if so </br>
     * ... it "sets" the new text</br>
     * else</br>
     * ... it "makes" the new text</br>
     * and "shows" either or  
     * @param st the string to be toasted
     */

    public void showAToast (String st){ //"Toast toast" is declared in the class
        try{ toast.getView().isShown();     // true if visible
            toast.setText(st);
        } catch (Exception e) {         // invisible if exception
            toast = Toast.makeText(theContext, st, toastDuration);
            }
        toast.show();  //finally display it
    }

Prüfen Sie, ob Toastmeldungen auf dem Bildschirm angezeigt werden oder nicht. Zum Anzeigen einer Toastnachricht Erstellen Sie eine separate Klasse. Verwenden Sie die Methode dieser Klasse, die die Toastnachricht anzeigt, nachdem Sie die Sichtbarkeit der Toastnachricht überprüft haben. Verwenden Sie diesen Codeausschnitt:

public class AppToast {

private static Toast toast;

public static void showToast(Context context, String message) {
    try {
        if (!toast.getView().isShown()) {
            toast=Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toast.show();
        }
    } catch (Exception ex) {
        toast=Toast.makeText(context,message,Toast.LENGTH_SHORT);
        toast.show();
    }
}

}

Ich hoffe, diese Lösung wird Ihnen helfen.

Vielen Dank







android-toast