OnGlobalLayoutListener: Veraltet und Kompatibilität

75

Ich muss ein OnGlobalLayoutListenerObjekt verwenden und dann, um den Listener zu entfernen, hatte ich ein Problem mit veralteten Methoden, die ich mit folgendem Code löse.

protected void onCreate(Bundle savedInstanceState) {
    final LinearLayout llTotal = (LinearLayout) findViewById(R.id.mmc_ll);
    ViewTreeObserver vto = llTotal.getViewTreeObserver();
    if(vto.isAlive()){
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //
                // mycode
                //
                if (Build.VERSION.SDK_INT<16) {
                    removeLayoutListenerPre16(llTotal.getViewTreeObserver(),this);
                } else {
                    removeLayoutListenerPost16(llTotal.getViewTreeObserver(), this);
                }
            } 
        });
    }
    super.onCreate(savedInstanceState);
}

@SuppressWarnings("deprecation")
private void removeLayoutListenerPre16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
    observer.removeGlobalOnLayoutListener(listener);
}

@TargetApi(16)
private void removeLayoutListenerPost16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
    observer.removeOnGlobalLayoutListener(listener);
}

Ist es richtig? Gibt es einen besseren Weg, um mit Kompatibilität umzugehen?

Ausführen des Codes im Emulator mit API 10 Ich habe die folgende Warnung in LogCat

04-24 09:30:12.565: I/dalvikvm(471): Could not find method android.view.ViewTreeObserver.removeOnGlobalLayoutListener, referenced from method com.my.project.ActivityHome.removeLayoutListenerPost16
04-24 09:30:12.565: W/dalvikvm(471): VFY: unable to resolve virtual method 2950: Landroid/view/ViewTreeObserver;.removeOnGlobalLayoutListener (Landroid/view/ViewTreeObserver$OnGlobalLayoutListener;)V

Kann ich sie ignorieren, wenn ich sie irgendwie reparieren muss?

crbin1
quelle

Antworten:

142

Ich benutze dies in meinem Projekt:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){
    if (Build.VERSION.SDK_INT < 16) {
        v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
    } else {
        v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
    }
}

sieht dir ähnlich. Getestet auf verschiedenen Geräten (4.2.2 & 2.3.3) und es läuft perfekt. Es scheint, als wäre es der einzige Weg ... Wenn Sie noch etwas finden, würde ich es gerne wissen. Viel Glück

2020 EDIT Dieser Ansatz ist sehr, sehr veraltet. Ich hoffe, Sie haben Ihren Code nach Kotlin verschoben. Jetzt können wir die Funktion doOnPreDraw verwenden, wenn wir die ktx-Bibliothek verwenden. https://developer.android.com/reference/kotlin/androidx/core/view/package-summary#(android.view.View).doOnPreDraw(kotlin.Function1)

Udi Oshi
quelle
Am Anfang habe ich Ihren Code verwendet, aber er gibt einen Fehler aus (Aufruf erfordert API-Level 16 (derzeit mindestens 8): android.view.ViewTreeObserver # removeOnGlobalLayoutListener) und eine Warnung (Die Methode removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener) vom Typ ViewT veraltet). Mein Code behebt diese Probleme, gibt aber die LogCat-Warnung
crbin1
Warnung ist in Ordnung. Dies liegt daran, dass Sie jar einer SDK-Version mit veralteter Funktion für Geräte <SDK verwenden. Sie können es also weiterhin verwenden.
Udi Oshi
9
@ crbin1 Sie können @TargetApi (Build.VERSION_CODES.JELLY_BEAN) vor der Funktionsdeklaration hinzufügen, wenn Sie diese Warnung / diesen Fehler vermeiden möchten.
Android-Entwickler
7
Google, das ist schrecklich.
Oliver Dixon
39

Ich denke, der richtige Weg ist Build.VERSION.SDK_INTund Build.VERSION_CODES:

public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
            } else {
                v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
            }
}
Jorgesys
quelle
1
Ich glaube , Sie wollen den Hörer zu übergeben removeGlobalLayoutListenerstattthis
Sergio Serra
10
    mView.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                //noinspection deprecation
                mView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
            //
            // mycode
            //
        } 
    });
Mathias Jeppsson
quelle
9

Natürlich ist es viel vorsichtiger, die Android-Version zu überprüfen und die richtige Methode aufzurufen, aber wenn Sie sich den Android-Quellcode ansehen, sehen Sie etwas Interessantes:

 @Deprecated
    public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) {
        removeOnGlobalLayoutListener(victim);
    }

Dieser Code wurde aus API 18 abgeschnitten

Gilian
quelle
5

Laut den Dokumenten :

Diese Methode wurde in API-Level 16 nicht mehr unterstützt. Verwenden Sie stattdessen #removeOnGlobalLayoutListener

Klappt wunderbar.

Bassem Wissa
quelle