mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add debugDisposed to Image (flutter/engine#21547)
This commit is contained in:
parent
76ba5d011f
commit
ab0d43bf69
@ -1632,6 +1632,19 @@ class Image {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this reference to the underlying image is [dispose]d.
|
||||
///
|
||||
/// This only returns a valid value if asserts are enabled, and must not be
|
||||
/// used otherwise.
|
||||
bool get debugDisposed {
|
||||
bool? disposed;
|
||||
assert(() {
|
||||
disposed = _disposed;
|
||||
return true;
|
||||
}());
|
||||
return disposed ?? (throw StateError('Image.debugDisposed is only available when asserts are enabled.'));
|
||||
}
|
||||
|
||||
/// Converts the [Image] object into a byte array.
|
||||
///
|
||||
/// The [format] argument specifies the format in which the bytes will be
|
||||
|
||||
@ -54,12 +54,21 @@ class CkAnimatedImage implements ui.Image {
|
||||
}
|
||||
}
|
||||
|
||||
bool _disposed = false;
|
||||
@override
|
||||
void dispose() {
|
||||
box.delete();
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get debugDisposed {
|
||||
if (assertionsEnabled) {
|
||||
return _disposed;
|
||||
}
|
||||
throw StateError('Image.debugDisposed is only available when asserts are enabled.');
|
||||
}
|
||||
|
||||
ui.Image clone() => CkAnimatedImage._(_skAnimatedImage, box);
|
||||
|
||||
@override
|
||||
@ -138,9 +147,22 @@ class CkImage implements ui.Image {
|
||||
}
|
||||
}
|
||||
|
||||
bool _disposed = false;
|
||||
@override
|
||||
void dispose() {
|
||||
box.delete();
|
||||
assert(() {
|
||||
_disposed = true;
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
|
||||
@override
|
||||
bool get debugDisposed {
|
||||
if (assertionsEnabled) {
|
||||
return _disposed;
|
||||
}
|
||||
throw StateError('Image.debugDisposed is only available when asserts are enabled.');
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -116,12 +116,25 @@ class HtmlImage implements ui.Image {
|
||||
bool _requiresClone = false;
|
||||
HtmlImage(this.imgElement, this.width, this.height);
|
||||
|
||||
bool _disposed = false;
|
||||
@override
|
||||
void dispose() {
|
||||
// Do nothing. The codec that owns this image should take care of
|
||||
// releasing the object url.
|
||||
if (assertionsEnabled) {
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool get debugDisposed {
|
||||
if (assertionsEnabled) {
|
||||
return _disposed;
|
||||
}
|
||||
return throw StateError('Image.debugDisposed is only available when asserts are enabled.');
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
ui.Image clone() => this;
|
||||
|
||||
|
||||
@ -329,6 +329,7 @@ abstract class Image {
|
||||
int get height;
|
||||
Future<ByteData?> toByteData({ImageByteFormat format = ImageByteFormat.rawRgba});
|
||||
void dispose();
|
||||
bool get debugDisposed;
|
||||
|
||||
Image clone() => this;
|
||||
|
||||
|
||||
@ -32,10 +32,13 @@ void testMain() {
|
||||
final SkAnimatedImage skAnimatedImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
final CkAnimatedImage image = CkAnimatedImage(skAnimatedImage);
|
||||
expect(image.box.isDeleted, false);
|
||||
expect(image.debugDisposed, false);
|
||||
image.dispose();
|
||||
expect(image.box.isDeleted, true);
|
||||
expect(image.debugDisposed, true);
|
||||
image.dispose();
|
||||
expect(image.box.isDeleted, true);
|
||||
expect(image.debugDisposed, true);
|
||||
});
|
||||
|
||||
test('CkAnimatedImage can be cloned and explicitly disposed of', () async {
|
||||
@ -69,10 +72,13 @@ void testMain() {
|
||||
test('CkImage can be explicitly disposed of', () {
|
||||
final SkImage skImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage).getCurrentFrame();
|
||||
final CkImage image = CkImage(skImage);
|
||||
expect(image.debugDisposed, false);
|
||||
expect(image.box.isDeleted, false);
|
||||
image.dispose();
|
||||
expect(image.debugDisposed, true);
|
||||
expect(image.box.isDeleted, true);
|
||||
image.dispose();
|
||||
expect(image.debugDisposed, true);
|
||||
expect(image.box.isDeleted, true);
|
||||
});
|
||||
|
||||
|
||||
@ -63,6 +63,14 @@ void testMain() async {
|
||||
expect(frameInfo.image.width, 100);
|
||||
expect(frameInfo.image.toString(), '[100×100]');
|
||||
});
|
||||
test('dispose image image', () async {
|
||||
final HtmlCodec codec = HtmlCodec('sample_image1.png');
|
||||
final ui.FrameInfo frameInfo = await codec.getNextFrame();
|
||||
expect(frameInfo.image, isNotNull);
|
||||
expect(frameInfo.image.debugDisposed, false);
|
||||
frameInfo.image.dispose();
|
||||
expect(frameInfo.image.debugDisposed, true);
|
||||
});
|
||||
test('provides image loading progress', () async {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
final HtmlCodec codec = HtmlCodec('sample_image1.png',
|
||||
|
||||
@ -723,6 +723,9 @@ class TestImage implements Image {
|
||||
@override
|
||||
void dispose() {}
|
||||
|
||||
@override
|
||||
bool get debugDisposed => false;
|
||||
|
||||
@override
|
||||
Image clone() => this;
|
||||
|
||||
|
||||
@ -126,6 +126,25 @@ void main() {
|
||||
expect(frame2.image.clone()..dispose(), isNotNull);
|
||||
frame2.image.dispose();
|
||||
});
|
||||
|
||||
test('debugDisposed works', () async {
|
||||
final Uint8List bytes = await readFile('2x2.png');
|
||||
final Codec codec = await instantiateImageCodec(bytes);
|
||||
final FrameInfo frame = await codec.getNextFrame();
|
||||
|
||||
if (assertsEnabled) {
|
||||
expect(frame.image.debugDisposed, false);
|
||||
} else {
|
||||
expect(() => frame.image.debugDisposed, throwsStateError);
|
||||
}
|
||||
|
||||
frame.image.dispose();
|
||||
if (assertsEnabled) {
|
||||
expect(frame.image.debugDisposed, true);
|
||||
} else {
|
||||
expect(() => frame.image.debugDisposed, throwsStateError);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<Uint8List> readFile(String fileName) async {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user