Skip to content

Commit

Permalink
[flutter_markdown] Fix some memory leaks and activate leak testing [p…
Browse files Browse the repository at this point in the history
…rod-leak-fix] (#8367)
  • Loading branch information
ValentinVignal authored Jan 5, 2025
1 parent 733869c commit 15f5484
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 25 deletions.
3 changes: 2 additions & 1 deletion packages/flutter_markdown/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT
## 0.7.5

* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
* Fixes some memory leaks.

## 0.7.4+3

Expand Down
77 changes: 58 additions & 19 deletions packages/flutter_markdown/lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -346,16 +346,20 @@ class MarkdownBuilder implements md.NodeVisitor {
child = builders[_blocks.last.tag!]!
.visitText(text, styleSheet.styles[_blocks.last.tag!]);
} else if (_blocks.last.tag == 'pre') {
final ScrollController preScrollController = ScrollController();
child = Scrollbar(
controller: preScrollController,
child: SingleChildScrollView(
controller: preScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.codeblockPadding,
child: _buildRichText(delegate.formatText(styleSheet, text.text)),
),
);
child = _ScrollControllerBuilder(
builder: (BuildContext context, ScrollController preScrollController,
Widget? child) {
return Scrollbar(
controller: preScrollController,
child: SingleChildScrollView(
controller: preScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.codeblockPadding,
child: child,
),
);
},
child: _buildRichText(delegate.formatText(styleSheet, text.text)));
} else {
child = _buildRichText(
TextSpan(
Expand Down Expand Up @@ -448,15 +452,20 @@ class MarkdownBuilder implements md.NodeVisitor {
}
} else if (tag == 'table') {
if (styleSheet.tableColumnWidth is FixedColumnWidth) {
final ScrollController tableScrollController = ScrollController();
child = Scrollbar(
controller: tableScrollController,
child: SingleChildScrollView(
controller: tableScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.tablePadding,
child: _buildTable(),
),
child = _ScrollControllerBuilder(
builder: (BuildContext context,
ScrollController tableScrollController, Widget? child) {
return Scrollbar(
controller: tableScrollController,
child: SingleChildScrollView(
controller: tableScrollController,
scrollDirection: Axis.horizontal,
padding: styleSheet.tablePadding,
child: child,
),
);
},
child: _buildTable(),
);
} else {
child = _buildTable();
Expand Down Expand Up @@ -1017,3 +1026,33 @@ class MarkdownBuilder implements md.NodeVisitor {
}
}
}

class _ScrollControllerBuilder extends StatefulWidget {
const _ScrollControllerBuilder({
required this.builder,
this.child,
});

final ValueWidgetBuilder<ScrollController> builder;

final Widget? child;

@override
State<_ScrollControllerBuilder> createState() =>
_ScrollControllerBuilderState();
}

class _ScrollControllerBuilderState extends State<_ScrollControllerBuilder> {
final ScrollController _controller = ScrollController();

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

@override
Widget build(BuildContext context) {
return widget.builder(context, _controller, widget.child);
}
}
3 changes: 2 additions & 1 deletion packages/flutter_markdown/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output,
formatted with simple Markdown tags.
repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22
version: 0.7.4+3
version: 0.7.5

environment:
sdk: ^3.4.0
Expand All @@ -20,6 +20,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
leak_tracker_flutter_testing: any
mockito: ^5.4.4
standard_message_codec: ^0.0.1+3

Expand Down
9 changes: 6 additions & 3 deletions packages/flutter_markdown/test/custom_syntax_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,12 @@ class WikilinkSyntax extends md.InlineSyntax {
class WikilinkBuilder extends MarkdownElementBuilder {
@override
Widget visitElementAfter(md.Element element, _) {
return Text.rich(TextSpan(
text: element.textContent,
recognizer: TapGestureRecognizer()..onTap = () {}));
final TapGestureRecognizer recognizer = TapGestureRecognizer()
..onTap = () {};
addTearDown(recognizer.dispose);
return Text.rich(
TextSpan(text: element.textContent, recognizer: recognizer),
);
}
}

Expand Down
13 changes: 13 additions & 0 deletions packages/flutter_markdown/test/flutter_test_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
LeakTesting.enable();
LeakTracking.warnForUnsupportedPlatforms = false;
await testMain();
}
1 change: 1 addition & 0 deletions packages/flutter_markdown/test/image_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ void defineTests() {
find.byType(Container),
matchesGoldenFile(
'assets/images/golden/image_test/custom_builder_asset_logo.png'));
imageCache.clear();
},
skip: kIsWeb, // Goldens are platform-specific.
);
Expand Down
3 changes: 2 additions & 1 deletion packages/flutter_markdown/test/link_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void defineTests() {
testWidgets(
'multiple inline links with same content should not throw an exception',
(WidgetTester tester) async {
//Arange
//Arrange
final Widget toBePumped = boilerplate(
Column(
children: <Widget>[
Expand Down Expand Up @@ -1477,6 +1477,7 @@ void defineTests() {

gestureWidget.onTap!();
expectLinkTap(linkTapResults, const MarkdownLink('moon', '/uri'));
imageCache.clear();
},
);

Expand Down
1 change: 1 addition & 0 deletions packages/flutter_markdown/test/padding_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ void defineTests() {
paddings[3].padding.along(Axis.horizontal) == paddingX * 4 * 2,
true,
);
imageCache.clear();
},
);
});
Expand Down
1 change: 1 addition & 0 deletions packages/flutter_markdown/test/scrollable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ void defineTests() {
final ScrollController controller = ScrollController(
initialScrollOffset: 209.0,
);
addTearDown(controller.dispose);

await tester.pumpWidget(
boilerplate(
Expand Down

0 comments on commit 15f5484

Please sign in to comment.