Удалить слушателя из ViewTreeObserver

Мне нужно прослушивать точное одно глобальное событие компоновки, чтобы первоначально установить правильные позиции прокрутки. После небольшого поиска, почему мои вызовы на scrollTo(x,y) кажутся проигнорированными, я обнаружил, что они могут быть вызваны значимым образом только после того, как будет известна вся макет. Поэтому я регистрирую GlobalLayoutListener и откладываю мой вызов на scrollTo().

Проблема в том, что я только хочу сделать эту прокрутку один раз. Поэтому я решил, что могу просто позвонить removeGlobalOnLayoutListener(), чтобы прекратить слушать. Это привело к исключению: IllegalStateException: This ViewTreeObserver is not alive, call getViewTreeObserver() again. Поэтому я думал, что я в порядке, если Наблюдатель не жив, он не возбудит никаких событий. Но, к сожалению, это происходит: мой взгляд прокручивается каждый раз, когда макет каким-то образом изменяется.

Моя текущая итерация кода выглядит так. Что я могу изменить, чтобы удостовериться, что вызов scrollToGridPos() происходит только один раз? Я знаю, что я мог бы добавить локальное поле mHasFired во внутренний класс, но это кажется очень грязным взломом для меня...

final ViewTreeObserver vto = mLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    public void onGlobalLayout() {
        scrollToGridPos(getCenterPoint(), false);
        if (vto.isAlive()) {
            vto.removeGlobalOnLayoutListener(this);
        }
    }
});

Ответ 1

Вы должны просто использовать mLayout.getViewTreeObserver() в onGlobalLayout(), а не пытаться получить доступ к старой. Например.

mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    public void onGlobalLayout() {
        scrollToGridPos(getCenterPoint(), false);
        mLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);        
    }
});