Как избавиться от неиспользуемых виджетов GWT - PullRequest
0 голосов
/ 22 мая 2019

Модуль пользовательского интерфейса GWT + GXT, над которым я работаю, использует переключение между панелями для получения различных видов представлений.Очень упрощенный пример:

mainPanel.add(successPanel);

ИЛИ

mainPanel.add(errorPanel);

Я заметил, что если errorPanel никогда не используется (прикрепляется), он никогда не удаляется.

Я знаю, чтодобавление обоих элементов пользовательского интерфейса в DOM и переключение видимости должно привести к тому же результату и обеспечить надлежащий сборщик мусора, но рефакторинг всего, что может сделать, может привести к множеству других проблем.

Я пробовал следующие методы:

  • присоединение неиспользуемых элементов к RootPanel и последующий вызов widget.removeFromParent ().
  • добавление неиспользуемых элементов в активный элемент DOM непосредственно перед тем, как этот активный элемент будет удален
  • Вызов DOM.setEventListener (widget.getElement (), null).
  • создание вспомогательного класса, предоставляющего метод removeMethod независимо от состояния вложения:
  public static void removeWidget(Widget w) {
    if (w.getParent() == null) {
      RootPanel.get().add(w);
      if (RootPanel.isInDetachList(w)) {
        RootPanel.detachNow(w);
      } else {
        try {
          // onUnload() gets called *before* everything else (the opposite of
          // onLoad()).
          w.onUnload();
          AttachEvent.fire(w, false);
        } catch (Exception e) {
          // ??? throws "Should only call onDetach when the widget is attached to the browser's document"
        } finally {
          // Put this in a finally, just in case onUnload throws an exception.
          try {
            w.doDetachChildren();
          } catch (Exception e) {
            // ???
          } finally {
            // Put this in a finally, in case doDetachChildren throws an exception.
            DOM.setEventListener(w.getElement(), null);
            //w.attached = false; // ??
          }
        }
      }
    } else if (w instanceof HasWidgets) {
      ((HasWidgets) w).remove(w);
    } else if (w != null) {
      throw new IllegalStateException("This widget's parent does not implement HasWidgets");
    }

  }

Ни один из этихметоды работали надежно.Есть ли способ пометить неиспользуемый виджет как ненужный и заставить GWT обрабатывать все удаление, включая его дочерние элементы?

Как-то связано с моим вопросом, есть ли способ выяснить, какие виджеты / классы не используютсяУтилизирован, если не считать трекера "Roll-Your-Yourself"?

1 Ответ

3 голосов
/ 22 мая 2019

Для GWT Widget нет «утилизации» - есть только присоединение / отсоединение.Если виджет отсоединен (или никогда не подключен), тогда обычная сборка мусора будет работать, если у вас нет ссылок на нее.

Если вы оставите его в «прикрепленном» режиме, но фактически удалите все ссылки на него (вручнуюудаление его из DOM или ручное включение присоединения без фактического помещения его в DOM и т. д.) приведет к утечке памяти в некоторых браузерах (древний Firefox, IE6-9 или 10 и т. д.).

Ваши шаги прохождения прикрепления и отсоединения имеют тот же эффект, что и никогда не прикреплять его с самого начала.Ваша утечка где-то еще, а не в жизненном цикле GWT Widget.В GWT нет «утилизации» - пока он фактически не подключен, достаточно обычного GC.

...