Instrument ImageInfo. (#141411)
This commit is contained in:
parent
7ff5f81a2e
commit
15fa68ab1d
@ -8,38 +8,55 @@ import 'dart:ui' as ui show Codec, FrameInfo, Image;
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
const String _flutterWidgetsLibrary = 'package:flutter/widgets.dart';
|
const String _flutterPaintingLibrary = 'package:flutter/painting.dart';
|
||||||
|
|
||||||
/// A [dart:ui.Image] object with its corresponding scale.
|
/// A [dart:ui.Image] object with its corresponding scale.
|
||||||
///
|
///
|
||||||
/// ImageInfo objects are used by [ImageStream] objects to represent the
|
/// ImageInfo objects are used by [ImageStream] objects to represent the
|
||||||
/// actual data of the image once it has been obtained.
|
/// actual data of the image once it has been obtained.
|
||||||
///
|
///
|
||||||
/// The receiver of an [ImageInfo] object must call [dispose]. To safely share
|
/// The disposing contract for [ImageInfo] (as well as for [ui.Image])
|
||||||
/// the object with other clients, use the [clone] method before calling
|
/// is different from traditional one, where
|
||||||
/// dispose.
|
/// an object should dispose a member if the object created the member.
|
||||||
|
/// Instead, the disposal contract is as follows:
|
||||||
|
///
|
||||||
|
/// * [ImageInfo] disposes [image], even if it is received as a constructor argument.
|
||||||
|
/// * [ImageInfo] is expected to be disposed not by the object, that created it,
|
||||||
|
/// but by the object that owns reference to it.
|
||||||
|
/// * It is expected that only one object owns reference to [ImageInfo] object.
|
||||||
|
///
|
||||||
|
/// Safety tips:
|
||||||
|
///
|
||||||
|
/// * To share the [ImageInfo] or [ui.Image] between objects, use the [clone] method,
|
||||||
|
/// which will not clone the entire underlying image, but only reference to it and information about it.
|
||||||
|
/// * After passing a [ui.Image] or [ImageInfo] reference to another object,
|
||||||
|
/// release the reference.
|
||||||
@immutable
|
@immutable
|
||||||
class ImageInfo {
|
class ImageInfo {
|
||||||
/// Creates an [ImageInfo] object for the given [image] and [scale].
|
/// Creates an [ImageInfo] object for the given [image] and [scale].
|
||||||
///
|
///
|
||||||
/// The [debugLabel] may be used to identify the source of this image.
|
/// The [debugLabel] may be used to identify the source of this image.
|
||||||
const ImageInfo({ required this.image, this.scale = 1.0, this.debugLabel });
|
///
|
||||||
|
/// See details for disposing contract in the class description.
|
||||||
|
ImageInfo({ required this.image, this.scale = 1.0, this.debugLabel }) {
|
||||||
|
if (kFlutterMemoryAllocationsEnabled) {
|
||||||
|
MemoryAllocations.instance.dispatchObjectCreated(
|
||||||
|
library: _flutterPaintingLibrary,
|
||||||
|
className: '$ImageInfo',
|
||||||
|
object: this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates an [ImageInfo] with a cloned [image].
|
/// Creates an [ImageInfo] with a cloned [image].
|
||||||
///
|
///
|
||||||
/// Once all outstanding references to the [image] are disposed, it is no
|
|
||||||
/// longer safe to access properties of it or attempt to draw it. Clones serve
|
|
||||||
/// to create new references to the underlying image data that can safely be
|
|
||||||
/// disposed without knowledge of whether some other reference holder will
|
|
||||||
/// still need access to the underlying image. Once a client disposes of its
|
|
||||||
/// own image reference, it can no longer access the image, but other clients
|
|
||||||
/// will be able to access their own references.
|
|
||||||
///
|
|
||||||
/// This method must be used in cases where a client holding an [ImageInfo]
|
/// This method must be used in cases where a client holding an [ImageInfo]
|
||||||
/// needs to share the image info object with another client and will still
|
/// needs to share the image info object with another client and will still
|
||||||
/// need to access the underlying image data at some later point, e.g. to
|
/// need to access the underlying image data at some later point, e.g. to
|
||||||
/// share it again with another client.
|
/// share it again with another client.
|
||||||
///
|
///
|
||||||
|
/// See details for disposing contract in the class description.
|
||||||
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [Image.clone], which describes how and why to clone images.
|
/// * [Image.clone], which describes how and why to clone images.
|
||||||
@ -125,6 +142,9 @@ class ImageInfo {
|
|||||||
/// and no clones of it or the image it contains can be made.
|
/// and no clones of it or the image it contains can be made.
|
||||||
void dispose() {
|
void dispose() {
|
||||||
assert((image.debugGetOpenHandleStackTraces()?.length ?? 1) > 0);
|
assert((image.debugGetOpenHandleStackTraces()?.length ?? 1) > 0);
|
||||||
|
if (kFlutterMemoryAllocationsEnabled) {
|
||||||
|
MemoryAllocations.instance.dispatchObjectDisposed(object: this);
|
||||||
|
}
|
||||||
image.dispose();
|
image.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +463,7 @@ class ImageStreamCompleterHandle {
|
|||||||
// https://github.com/flutter/flutter/issues/137435
|
// https://github.com/flutter/flutter/issues/137435
|
||||||
if (kFlutterMemoryAllocationsEnabled) {
|
if (kFlutterMemoryAllocationsEnabled) {
|
||||||
FlutterMemoryAllocations.instance.dispatchObjectCreated(
|
FlutterMemoryAllocations.instance.dispatchObjectCreated(
|
||||||
library: _flutterWidgetsLibrary,
|
library: _flutterPaintingLibrary,
|
||||||
className: '$ImageStreamCompleterHandle',
|
className: '$ImageStreamCompleterHandle',
|
||||||
object: this,
|
object: this,
|
||||||
);
|
);
|
||||||
|
@ -891,4 +891,17 @@ void main() {
|
|||||||
areCreateAndDispose,
|
areCreateAndDispose,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('ImageInfo dispatches memory events', (WidgetTester tester) async {
|
||||||
|
await expectLater(
|
||||||
|
await memoryEvents(
|
||||||
|
() async {
|
||||||
|
final ImageInfo info = ImageInfo(image: image20x10);
|
||||||
|
info.dispose();
|
||||||
|
},
|
||||||
|
ImageInfo,
|
||||||
|
),
|
||||||
|
areCreateAndDispose,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
|
|
||||||
class TestImageInfo extends ImageInfo {
|
class TestImageInfo extends ImageInfo {
|
||||||
const TestImageInfo(this.value, {
|
TestImageInfo(this.value, {
|
||||||
required super.image,
|
required super.image,
|
||||||
super.scale,
|
super.scale,
|
||||||
super.debugLabel,
|
super.debugLabel,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user