Skip to content

Commit

Permalink
fix: fix renderObject and element memory leaks.
Browse files Browse the repository at this point in the history
  • Loading branch information
andycall committed Nov 23, 2021
1 parent 9197146 commit abb458a
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 11 deletions.
13 changes: 9 additions & 4 deletions kraken/lib/src/css/overflow.dart
Expand Up @@ -105,6 +105,11 @@ mixin ElementOverflowMixin on ElementBase {
KrakenScrollable? _scrollableX;
KrakenScrollable? _scrollableY;

void disposeScrolling() {
_scrollableX = null;
_scrollableY = null;
}

void updateRenderBoxModelWithOverflowX(ScrollListener scrollListener) {
if (renderBoxModel is RenderSliverListLayout) {
RenderSliverListLayout renderBoxModel = this.renderBoxModel as RenderSliverListLayout;
Expand Down Expand Up @@ -147,7 +152,7 @@ mixin ElementOverflowMixin on ElementBase {
}

renderBoxModel.scrollListener = scrollListener;
renderBoxModel.pointerListener = _pointerListener;
renderBoxModel.scrollPointerListener = _scrollPointerListener;

if (renderBoxModel is RenderLayoutBox) {
if (shouldScrolling) {
Expand Down Expand Up @@ -199,7 +204,7 @@ mixin ElementOverflowMixin on ElementBase {
}

renderBoxModel.scrollListener = scrollListener;
renderBoxModel.pointerListener = _pointerListener;
renderBoxModel.scrollPointerListener = _scrollPointerListener;

if (renderBoxModel is RenderLayoutBox) {
if (shouldScrolling) {
Expand All @@ -214,7 +219,7 @@ mixin ElementOverflowMixin on ElementBase {
void scrollingContentBoxStyleListener(String property, String? original, String present) {
RenderLayoutBox scrollingContentBox = (renderBoxModel as RenderLayoutBox).renderScrollingContent!;
RenderStyle scrollingContentRenderStyle = scrollingContentBox.renderStyle;

switch (property) {
case DISPLAY:
scrollingContentRenderStyle.display = renderStyle.display;
Expand Down Expand Up @@ -334,7 +339,7 @@ mixin ElementOverflowMixin on ElementBase {
outerLayoutBox.addAll(children);
}

void _pointerListener(PointerEvent event) {
void _scrollPointerListener(PointerEvent event) {
if (event is PointerDownEvent) {
if (_scrollableX != null) {
_scrollableX!.handlePointerDown(event);
Expand Down
6 changes: 5 additions & 1 deletion kraken/lib/src/dom/element.dart
Expand Up @@ -412,6 +412,9 @@ class Element extends Node

// Remove renderBox.
_removeRenderBoxModel(renderBoxModel!);

// Remove pointer listener
removeEventResponder(renderBoxModel!);
}

@override
Expand Down Expand Up @@ -555,6 +558,7 @@ class Element extends Node
renderStyle.detach();
style.dispose();
properties.clear();
disposeScrolling();

super.dispose();
}
Expand Down Expand Up @@ -1703,8 +1707,8 @@ bool _hasIntersectionObserverEvent(Map eventHandlers) {
void _detachRenderBoxModel(RenderBox renderBox) {
if (renderBox.parent == null) return;

// Remove reference from parent
RenderObject? parentRenderObject = renderBox.parent as RenderObject;

if (parentRenderObject is RenderObjectWithChildMixin) {
parentRenderObject.child = null; // RenderViewportBox
} else if (parentRenderObject is ContainerRenderObjectMixin) {
Expand Down
1 change: 1 addition & 0 deletions kraken/lib/src/dom/event_handler.dart
Expand Up @@ -37,6 +37,7 @@ mixin ElementEventMixin on EventTarget {
renderBox.onLongPress = null;
renderBox.getEventTarget = null;
renderBox.dispatchEvent = null;
renderBox.getEventHandlers = null;
}

EventTarget getEventTarget() {
Expand Down
9 changes: 8 additions & 1 deletion kraken/lib/src/gesture/scrollable.dart
Expand Up @@ -239,7 +239,14 @@ class KrakenScrollable with _CustomTickerProviderStateMixin implements ScrollCon

mixin RenderOverflowMixin on RenderBox {
ScrollListener? scrollListener;
void Function(PointerEvent)? pointerListener;
void Function(PointerEvent)? scrollPointerListener;

void disposeScroll() {
scrollListener = null;
scrollPointerListener = null;
_scrollOffsetX = null;
_scrollOffsetY = null;
}

bool _clipX = false;
bool get clipX => _clipX;
Expand Down
29 changes: 26 additions & 3 deletions kraken/lib/src/rendering/box_model.dart
Expand Up @@ -172,6 +172,14 @@ class RenderLayoutBox extends RenderBoxModel
}
}

@override
void dispose() {
super.dispose();

paintingOrder.clear();
stickyChildren.clear();
}

@override
void markNeedsLayout() {
super.markNeedsLayout();
Expand Down Expand Up @@ -682,7 +690,7 @@ class RenderBoxModel extends RenderBox

// Copy overflow
..scrollListener = scrollListener
..pointerListener = pointerListener
..scrollPointerListener = scrollPointerListener
..clipX = clipX
..clipY = clipY
..enableScrollX = enableScrollX
Expand Down Expand Up @@ -1304,17 +1312,32 @@ class RenderBoxModel extends RenderBox
renderStyle.backgroundAttachment == CSSBackgroundAttachmentType.local;
}

void _detachAllChildren() {
if (this is RenderObjectWithChildMixin) {
(this as RenderObjectWithChildMixin).child = null;
} else if (this is ContainerRenderObjectMixin) {
(this as ContainerRenderObjectMixin).removeAll();
}
}

/// Called when its corresponding element disposed
@mustCallSuper
void dispose() {
// Clear renderObjects in list when disposed to avoid memory leak
if (fixedChildren.isNotEmpty) {
fixedChildren.clear();
}

// Dispose scroll behavior
disposeScroll();

// Dispose box decoration painter.
disposePainter();
// Evict render decoration image cache.
renderStyle.decoration?.image?.image.evict();

// Remove reference from childs
_detachAllChildren();
}

Offset getTotalScrollOffset() {
Expand Down Expand Up @@ -1428,8 +1451,8 @@ class RenderBoxModel extends RenderBox
@override
void handleEvent(PointerEvent event, HitTestEntry entry) {
super.handleEvent(event, entry);
if (pointerListener != null) {
pointerListener!(event);
if (scrollPointerListener != null) {
scrollPointerListener!(event);
}
}

Expand Down
9 changes: 9 additions & 0 deletions kraken/lib/src/rendering/flex.dart
Expand Up @@ -197,6 +197,15 @@ class RenderFlexLayout extends RenderLayoutBox {
return CSSFlex.isHorizontalFlexDirection(renderStyle.flexDirection);
}

@override
void dispose() {
super.dispose();

flexLineBoxMetrics.clear();
childrenIntrinsicMainSizes.clear();
childrenOldConstraints.clear();
}

double _getIntrinsicSize({
FlexDirection? sizingDirection,
double?
Expand Down
7 changes: 7 additions & 0 deletions kraken/lib/src/rendering/flow.dart
Expand Up @@ -175,6 +175,13 @@ class RenderFlowLayout extends RenderLayoutBox {
/// Line boxes of flow layout
List<_RunMetrics> lineBoxMetrics = <_RunMetrics>[];

@override
void dispose() {
super.dispose();

lineBoxMetrics.clear();
}

@override
void setupParentData(RenderBox child) {
if (child.parentData is! RenderLayoutParentData) {
Expand Down
4 changes: 2 additions & 2 deletions kraken/lib/src/rendering/sliver_list.dart
Expand Up @@ -42,7 +42,7 @@ class RenderSliverListLayout extends RenderLayoutBox {
}) : _renderSliverBoxChildManager = manager,
_scrollListener = onScroll,
super(renderStyle: renderStyle) {
pointerListener = _pointerListener;
scrollPointerListener = _scrollPointerListener;
scrollable = KrakenScrollable(axisDirection: getAxisDirection(axis));
axis = renderStyle.sliverDirection;

Expand Down Expand Up @@ -121,7 +121,7 @@ class RenderSliverListLayout extends RenderLayoutBox {
}
}

void _pointerListener(PointerEvent event) {
void _scrollPointerListener(PointerEvent event) {
if (event is PointerDownEvent) {
scrollable.handlePointerDown(event);
}
Expand Down

0 comments on commit abb458a

Please sign in to comment.