TextPainter should dispatch creation and disposal events. (#137416)
This commit is contained in:
parent
14f95576e5
commit
fea561301b
@ -664,6 +664,7 @@ class _SnackBarState extends State<SnackBar> {
|
||||
final double actionAndIconWidth = actionTextPainter.size.width +
|
||||
(widget.action != null ? actionHorizontalMargin : 0) +
|
||||
(showCloseIcon ? (iconButton?.iconSize ?? 0 + iconHorizontalMargin) : 0);
|
||||
actionTextPainter.dispose();
|
||||
|
||||
final EdgeInsets margin = widget.margin?.resolve(TextDirection.ltr) ?? snackBarTheme.insetPadding ?? defaults.insetPadding!;
|
||||
|
||||
|
@ -1309,6 +1309,7 @@ class _SwitchPainter extends ToggleablePainter {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
final TextPainter _textPainter = TextPainter();
|
||||
Color? _cachedThumbColor;
|
||||
ImageProvider? _cachedThumbImage;
|
||||
ImageErrorListener? _cachedThumbErrorListener;
|
||||
@ -1594,16 +1595,15 @@ class _SwitchPainter extends ToggleablePainter {
|
||||
shadows: iconShadows,
|
||||
),
|
||||
);
|
||||
final TextPainter textPainter = TextPainter(
|
||||
textDirection: textDirection,
|
||||
text: textSpan,
|
||||
);
|
||||
textPainter.layout();
|
||||
_textPainter
|
||||
..textDirection = textDirection
|
||||
..text = textSpan;
|
||||
_textPainter.layout();
|
||||
final double additionalHorizontalOffset = (thumbSize.width - iconSize) / 2;
|
||||
final double additionalVerticalOffset = (thumbSize.height - iconSize) / 2;
|
||||
final Offset offset = thumbPaintOffset + Offset(additionalHorizontalOffset, additionalVerticalOffset);
|
||||
|
||||
textPainter.paint(canvas, offset);
|
||||
_textPainter.paint(canvas, offset);
|
||||
}
|
||||
} finally {
|
||||
_isPainting = false;
|
||||
@ -1612,6 +1612,7 @@ class _SwitchPainter extends ToggleablePainter {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textPainter.dispose();
|
||||
_cachedThumbPainter?.dispose();
|
||||
_cachedThumbPainter = null;
|
||||
_cachedThumbColor = null;
|
||||
|
@ -215,10 +215,15 @@ class _FlutterLogoPainter extends BoxPainter {
|
||||
final FlutterLogoDecoration _config;
|
||||
|
||||
// these are configured assuming a font size of 100.0.
|
||||
// TODO(dnfield): Figure out how to dispose this https://github.com/flutter/flutter/issues/110601
|
||||
late TextPainter _textPainter;
|
||||
late Rect _textBoundingRect;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textPainter.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _prepareText() {
|
||||
const String kLabel = 'Flutter';
|
||||
_textPainter = TextPainter(
|
||||
|
@ -438,6 +438,8 @@ final class _EmptyLineCaretMetrics implements _CaretMetrics {
|
||||
final double lineVerticalOffset;
|
||||
}
|
||||
|
||||
const String _flutterPaintingLibrary = 'package:flutter/painting.dart';
|
||||
|
||||
/// An object that paints a [TextSpan] tree into a [Canvas].
|
||||
///
|
||||
/// To use a [TextPainter], follow these steps:
|
||||
@ -498,7 +500,17 @@ class TextPainter {
|
||||
_locale = locale,
|
||||
_strutStyle = strutStyle,
|
||||
_textWidthBasis = textWidthBasis,
|
||||
_textHeightBehavior = textHeightBehavior;
|
||||
_textHeightBehavior = textHeightBehavior {
|
||||
// TODO(polina-c): stop duplicating code across disposables
|
||||
// https://github.com/flutter/flutter/issues/137435
|
||||
if (kFlutterMemoryAllocationsEnabled) {
|
||||
MemoryAllocations.instance.dispatchObjectCreated(
|
||||
library: _flutterPaintingLibrary,
|
||||
className: '$TextPainter',
|
||||
object: this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the width of a configured [TextPainter].
|
||||
///
|
||||
@ -1598,6 +1610,11 @@ class TextPainter {
|
||||
_disposed = true;
|
||||
return true;
|
||||
}());
|
||||
// TODO(polina-c): stop duplicating code across disposables
|
||||
// https://github.com/flutter/flutter/issues/137435
|
||||
if (kFlutterMemoryAllocationsEnabled) {
|
||||
MemoryAllocations.instance.dispatchObjectDisposed(object: this);
|
||||
}
|
||||
_layoutTemplate?.dispose();
|
||||
_layoutTemplate = null;
|
||||
_layoutCache?.paragraph.dispose();
|
||||
|
@ -2263,6 +2263,12 @@ class RenderDecoratedBox extends RenderProxyBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_painter?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestSelf(Offset position) {
|
||||
return _decoration.hitTest(size, position, textDirection: configuration.textDirection);
|
||||
|
@ -231,7 +231,7 @@ class BannerPainter extends CustomPainter {
|
||||
///
|
||||
/// * [CheckedModeBanner], which the [WidgetsApp] widget includes by default in
|
||||
/// debug mode, to show a banner that says "DEBUG".
|
||||
class Banner extends StatelessWidget {
|
||||
class Banner extends StatefulWidget {
|
||||
/// Creates a banner.
|
||||
const Banner({
|
||||
super.key,
|
||||
@ -288,31 +288,48 @@ class Banner extends StatelessWidget {
|
||||
/// The style of the text shown on the banner.
|
||||
final TextStyle textStyle;
|
||||
|
||||
@override
|
||||
State<Banner> createState() => _BannerState();
|
||||
}
|
||||
|
||||
class _BannerState extends State<Banner> {
|
||||
BannerPainter? _painter;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_painter?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert((textDirection != null && layoutDirection != null) || debugCheckHasDirectionality(context));
|
||||
assert((widget.textDirection != null && widget.layoutDirection != null) || debugCheckHasDirectionality(context));
|
||||
|
||||
_painter?.dispose();
|
||||
_painter = BannerPainter(
|
||||
message: widget.message,
|
||||
textDirection: widget.textDirection ?? Directionality.of(context),
|
||||
location: widget.location,
|
||||
layoutDirection: widget.layoutDirection ?? Directionality.of(context),
|
||||
color: widget.color,
|
||||
textStyle: widget.textStyle,
|
||||
);
|
||||
|
||||
return CustomPaint(
|
||||
foregroundPainter: BannerPainter(
|
||||
message: message,
|
||||
textDirection: textDirection ?? Directionality.of(context),
|
||||
location: location,
|
||||
layoutDirection: layoutDirection ?? Directionality.of(context),
|
||||
color: color,
|
||||
textStyle: textStyle,
|
||||
),
|
||||
child: child,
|
||||
foregroundPainter: _painter,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(StringProperty('message', message, showName: false));
|
||||
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
|
||||
properties.add(EnumProperty<BannerLocation>('location', location));
|
||||
properties.add(EnumProperty<TextDirection>('layoutDirection', layoutDirection, defaultValue: null));
|
||||
properties.add(ColorProperty('color', color, showName: false));
|
||||
textStyle.debugFillProperties(properties, prefix: 'text ');
|
||||
properties.add(StringProperty('message', widget.message, showName: false));
|
||||
properties.add(EnumProperty<TextDirection>('textDirection', widget.textDirection, defaultValue: null));
|
||||
properties.add(EnumProperty<BannerLocation>('location', widget.location));
|
||||
properties.add(EnumProperty<TextDirection>('layoutDirection', widget.layoutDirection, defaultValue: null));
|
||||
properties.add(ColorProperty('color', widget.color, showName: false));
|
||||
widget.textStyle.debugFillProperties(properties, prefix: 'text ');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
|
||||
|
||||
void _checkCaretOffsetsLtrAt(String text, List<int> boundaries) {
|
||||
expect(boundaries.first, 0);
|
||||
@ -1525,6 +1526,13 @@ void main() {
|
||||
expect(metrics, hasLength(1));
|
||||
}
|
||||
}, skip: kIsWeb && !isCanvasKit); // [intended] Browsers seem to always round font/glyph metrics.
|
||||
|
||||
test('TextPainter dispatches memory events', () async {
|
||||
await expectLater(
|
||||
await memoryEvents(() => TextPainter().dispose(), TextPainter),
|
||||
areCreateAndDispose,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
class MockCanvas extends Fake implements Canvas {
|
||||
|
Loading…
x
Reference in New Issue
Block a user