OnGlobalLayoutListener: застарілість та сумісність


75

Мені потрібно використовувати 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

Чи можу я проігнорувати їх, якщо я повинен якось виправити?

Відповіді:


142

Я використовую це у своєму проекті:

@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), і він працює ідеально. здається, це єдиний спосіб .... Якщо ви знайдете щось інше, я хотів би це знати. Щасти

2020 EDIT Цей підхід дуже застарів. Сподіваюся, ви перенесли свій код до Котліна. Тепер ми можемо використовувати функцію doOnPreDraw при використанні бібліотеки ktx. https://developer.android.com/reference/kotlin/androidx/core/view/package-summary#(android.view.View).doOnPreDraw(kotlin.Function1)


На початку я використав ваш код, але він видає помилку (для виклику потрібен рівень API 16 (поточний хв - 8): android.view.ViewTreeObserver # removeOnGlobalLayoutListener) і попередження (метод removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListenerO) із типу View ViewTistereeO) застарілий). Мій код вирішує ці проблеми, але дає попередження LogCat
crbin1

попередження добре. це тому, що ви використовуєте jar якоїсь версії sdk із застарілою функцією для пристроїв <sdk. так що ви все ще можете ним користуватися.
Уді Оші,

9
@ crbin1 ви можете додати @TargetApi (Build.VERSION_CODES.JELLY_BEAN) перед оголошенням функції, якщо ви хочете уникати бачення цього попередження / помилки.
розробник android

7
Google, це жахливо.
Олівер Діксон,

39

Я вважаю, що правильним є використання 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);
            }
}

1
Думаю, ви хочете передати слухача removeGlobalLayoutListenerзамістьthis
Серхіо Серра

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

Звичайно, перевіряти версію Android та називати правильний метод набагато розумніше, але якщо ви подивитесь на вихідний код Android, ви побачите щось цікаве:

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

Цей код було вилучено з API 18


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.