OnGlobalLayoutListener: устаревание и совместимость

Мне нужно использовать объект OnGlobalLayoutListener, а затем удалить слушателя, у меня возникла проблема с устаревшими методами, которые я разрешаю с помощью следующего кода.

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

Правильно ли это? Существует лучший способ справиться с совместимостью?

Запуск кода в эмуляторе с API 10 У меня есть следующее предупреждение в 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

Могу ли я игнорировать их, я должен что-то исправить?

Ответ 1

Я использую это в своем проекте:

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

похож на ваш. Протестировано на разных устройствах (4.2.2 и 2.3.3), и оно работает отлично. Кажется, это единственный способ... Если вы найдете что-нибудь еще, я бы хотел это знать. удачи

Ответ 2

Я думаю, что правильный способ - использовать Build.VERSION.SDK_INT и 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);
            }
}

Ответ 3

Конечно, проверка версии Android и вызов правильного метода гораздо более осмотрительны, но если вы посмотрите на исходный код Android, вы увидите что-то интересное:

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

Этот код был отключен от API 18

Ответ 4

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

Ответ 5

В соответствии с docs:

Этот метод устарел на уровне API 16. Вместо этого используйте #removeOnGlobalLayoutListener

Работает как шарм.