Правильное использование WindowManager.removeViewImmediate () - PullRequest
0 голосов
/ 09 октября 2018

Документация для WindowManager.removeViewImmediate() содержит предупреждение (выделено мной):

Специальный вариант ViewManager.removeView(View), который немедленно вызывает методы View.onDetachedFromWindow() данной иерархии представления передвозвращение. Это не для обычных приложений;его правильное использование требует большой осторожности.

Мне интересно, что именно здесь означает "большая забота".Предположительно, это признак того, что мне не следует вызывать этот метод, если я не знаю, как справиться со всеми побочными эффектами его использования ... но я даже не знаю, какими могут быть эти побочные эффекты.


Рассмотрим следующее задание, которое я сделал как можно более ванильным.Там нет пропущенного кода (кроме импорта), и тема Activity является просто ванильной темой AppCompat:

public class MainActivity extends AppCompatActivity {

    private View overlay;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().getDecorView().post(() -> {
            overlay = new View(this);
            overlay.setBackgroundColor(Color.RED);

            WindowManager.LayoutParams params =
                    new WindowManager.LayoutParams(WindowManager.LayoutParams.FLAG_FULLSCREEN);

            getWindowManager().addView(overlay, params);
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getWindowManager().removeView(overlay);
    }
}

Когда я запускаю свое приложение и поворачиваю свое устройство из портретной в альбомную (или что-то еще, что вызываетон должен быть уничтожен и воссоздан), это появляется в logcat:

2018-10-09 13:58:02.162 11270-11270/com.example.stackoverflow E/WindowManager: android.view.WindowLeaked: Activity com.example.stackoverflow.MainActivity has leaked window android.view.View{e99861 V.ED..... ........ 0,0-1080,1920} that was originally added here
        at android.view.ViewRootImpl.<init>(ViewRootImpl.java:511)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:346)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
        at com.example.stackoverflow.MainActivity.lambda$onCreate$0(MainActivity.java:25)

Однако, если я изменю свой метод onDestroy() на использование removeViewImmedate(), то эта ошибка никогда не будетпоявляется в моих журналах.Однако я не решаюсь сделать это, потому что не знаю, на что еще может повлиять переключение этих вызовов.Просто сказать «это работает» недостаточно, чтобы успокоить мой разум.

1 Ответ

0 голосов
/ 09 октября 2018

WinowManager реализуется WindowManagerImpl.

WindowManagerImpl#removeViewImmediate(View) и WindowManagerImpl#removeView(View) оба вызывают WindowManagerGlobal#removeView(View, boolean).

Разница в том, что removeViewImmediate() передает true этому логическому аргументу,который сообщает WindowManagerGlobal, что это представление должно быть удалено немедленно, а не в ожидании.

Хотя это, вероятно, довольно очевидно.

Единственное, о чем я могу подумать, это может сделать немедленное удаление проблемой, этостранные ошибки рисования.В то время как комментарии к исходным методам говорят следующее:

/ ** * @param немедленный True, сделайте сейчас, если не в обходе.Ложь, ставь в очередь и делай попозже.* @return Правда, запрос был поставлен в очередь.Неверно, запрос был выполнен.* /

В этом нет особого смысла.

Честно говоря, если это не вызывает сбоев и вместо этого удаляет это предупреждение об утечке, вы также можете использовать его.

WindowManagerGlobal # removeViewLocked (Просмотр, логическое значение)

ViewRootImpl # die (логическое значение)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...