76

I have to use an OnGlobalLayoutListener object and then to remove the listener, I had a problem with deprecated methods that I resolve with following code.

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);
}

Is it correct? There is a better way to handle compatibility?

Running the code in emulator with API 10 I have the following warning 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

Can I ignore them of I have to fix in some way?

crbin1
  • 2,219
  • 3
  • 22
  • 29

5 Answers5

146

I'm using this in my project:

@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);
    }
}

looks similar to yours. Tested on different devices (4.2.2 & 2.3.3) and it run perfectly. seems like it's the only way....If you find anything else I would like to know it. good luck

2020 EDIT This approach is very very obsolete. I hope you moved your code to Kotlin. Now we can use doOnPreDraw function when using ktx library. https://developer.android.com/reference/kotlin/androidx/core/view/package-summary#(android.view.View).doOnPreDraw(kotlin.Function1)

Udi Oshi
  • 6,787
  • 7
  • 47
  • 65
  • At the beginning I used your code but it give an error (Call requires API level 16 (current min is 8): android.view.ViewTreeObserver#removeOnGlobalLayoutListener) and a Warning (The method removeGlobalOnLayoutListener(ViewTreeObserver.OnGlobalLayoutListener) from the type ViewTreeObserver is deprecated). My code resolve those issues but give the LogCat warning – crbin1 Apr 24 '13 at 12:09
  • warning is fine. it's because you're using jar of some sdk version with deprecated function for devices < sdk. so you can still use it. – Udi Oshi Apr 24 '13 at 14:22
  • 9
    @crbin1 you can add @TargetApi(Build.VERSION_CODES.JELLY_BEAN) before the function declaration , if you wish to avoid seeing this warning/error. – android developer Jul 02 '13 at 07:53
  • 7
    Google, this is horrible. – Oliver Dixon Feb 02 '16 at 11:36
39

I think the correct way is using Build.VERSION.SDK_INT and 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);
            }
}
Greeny
  • 1,931
  • 2
  • 17
  • 26
Jorgesys
  • 124,308
  • 23
  • 334
  • 268
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
            //
        } 
    });
9

Of course that check the Android version and call the correct method is much more prudent, but if you take a look on the Android source code you can see something interesting:

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

This code was snipped from API 18

Gilian
  • 422
  • 7
  • 12
6

According to the docs:

This method was deprecated in API level 16. Use #removeOnGlobalLayoutListener instead

Works like a charm.

halfer
  • 19,824
  • 17
  • 99
  • 186
Bassem Wissa
  • 2,947
  • 1
  • 20
  • 20