Unverified Commit 4c7fae93 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Revert "migrate part of painting to nullsafety (#62696)" (#62868)

This reverts commit 4518a72f.
parent 0e558042
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show lerpDouble;
......@@ -87,12 +88,12 @@ abstract class AlignmentGeometry {
/// into a concrete [Alignment] using [resolve].
///
/// {@macro dart.ui.shadow.lerp}
static AlignmentGeometry? lerp(AlignmentGeometry? a, AlignmentGeometry? b, double t) {
static AlignmentGeometry lerp(AlignmentGeometry a, AlignmentGeometry b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return b! * t;
return b * t;
if (b == null)
return a * (1.0 - t);
if (a is Alignment && b is Alignment)
......@@ -100,9 +101,9 @@ abstract class AlignmentGeometry {
if (a is AlignmentDirectional && b is AlignmentDirectional)
return AlignmentDirectional.lerp(a, b, t);
return _MixedAlignment(
ui.lerpDouble(a._x, b._x, t)!,
ui.lerpDouble(a._start, b._start, t)!,
ui.lerpDouble(a._y, b._y, t)!,
ui.lerpDouble(a._x, b._x, t),
ui.lerpDouble(a._start, b._start, t),
ui.lerpDouble(a._y, b._y, t),
);
}
......@@ -115,7 +116,7 @@ abstract class AlignmentGeometry {
/// * [Alignment], for which this is a no-op (returns itself).
/// * [AlignmentDirectional], which flips the horizontal direction
/// based on the `direction` argument.
Alignment resolve(TextDirection? direction);
Alignment resolve(TextDirection direction);
@override
String toString() {
......@@ -332,19 +333,19 @@ class Alignment extends AlignmentGeometry {
/// If either is null, this function interpolates from [Alignment.center].
///
/// {@macro dart.ui.shadow.lerp}
static Alignment? lerp(Alignment? a, Alignment? b, double t) {
static Alignment lerp(Alignment a, Alignment b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return Alignment(ui.lerpDouble(0.0, b!.x, t)!, ui.lerpDouble(0.0, b.y, t)!);
return Alignment(ui.lerpDouble(0.0, b.x, t), ui.lerpDouble(0.0, b.y, t));
if (b == null)
return Alignment(ui.lerpDouble(a.x, 0.0, t)!, ui.lerpDouble(a.y, 0.0, t)!);
return Alignment(ui.lerpDouble(a.x, b.x, t)!, ui.lerpDouble(a.y, b.y, t)!);
return Alignment(ui.lerpDouble(a.x, 0.0, t), ui.lerpDouble(a.y, 0.0, t));
return Alignment(ui.lerpDouble(a.x, b.x, t), ui.lerpDouble(a.y, b.y, t));
}
@override
Alignment resolve(TextDirection? direction) => this;
Alignment resolve(TextDirection direction) => this;
static String _stringify(double x, double y) {
if (x == -1.0 && y == -1.0)
......@@ -513,26 +514,27 @@ class AlignmentDirectional extends AlignmentGeometry {
/// If either is null, this function interpolates from [AlignmentDirectional.center].
///
/// {@macro dart.ui.shadow.lerp}
static AlignmentDirectional? lerp(AlignmentDirectional? a, AlignmentDirectional? b, double t) {
static AlignmentDirectional lerp(AlignmentDirectional a, AlignmentDirectional b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return AlignmentDirectional(ui.lerpDouble(0.0, b!.start, t)!, ui.lerpDouble(0.0, b.y, t)!);
return AlignmentDirectional(ui.lerpDouble(0.0, b.start, t), ui.lerpDouble(0.0, b.y, t));
if (b == null)
return AlignmentDirectional(ui.lerpDouble(a.start, 0.0, t)!, ui.lerpDouble(a.y, 0.0, t)!);
return AlignmentDirectional(ui.lerpDouble(a.start, b.start, t)!, ui.lerpDouble(a.y, b.y, t)!);
return AlignmentDirectional(ui.lerpDouble(a.start, 0.0, t), ui.lerpDouble(a.y, 0.0, t));
return AlignmentDirectional(ui.lerpDouble(a.start, b.start, t), ui.lerpDouble(a.y, b.y, t));
}
@override
Alignment resolve(TextDirection? direction) {
Alignment resolve(TextDirection direction) {
assert(direction != null, 'Cannot resolve $runtimeType without a TextDirection.');
switch (direction!) {
switch (direction) {
case TextDirection.rtl:
return Alignment(-start, y);
case TextDirection.ltr:
return Alignment(start, y);
}
return null;
}
static String _stringify(double start, double y) {
......@@ -620,14 +622,15 @@ class _MixedAlignment extends AlignmentGeometry {
}
@override
Alignment resolve(TextDirection? direction) {
Alignment resolve(TextDirection direction) {
assert(direction != null, 'Cannot resolve $runtimeType without a TextDirection.');
switch (direction!) {
switch (direction) {
case TextDirection.rtl:
return Alignment(_x - _start, _y);
case TextDirection.ltr:
return Alignment(_x + _start, _y);
}
return null;
}
}
......@@ -649,7 +652,7 @@ class _MixedAlignment extends AlignmentGeometry {
class TextAlignVertical {
/// Creates a TextAlignVertical from any y value between -1.0 and 1.0.
const TextAlignVertical({
required this.y,
@required this.y,
}) : assert(y != null),
assert(y >= -1.0 && y <= 1.0);
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show TextDirection;
......@@ -142,6 +143,7 @@ Axis flipAxis(Axis direction) {
case Axis.vertical:
return Axis.horizontal;
}
return null;
}
/// A direction in which boxes flow vertically.
......@@ -212,6 +214,7 @@ Axis axisDirectionToAxis(AxisDirection axisDirection) {
case AxisDirection.right:
return Axis.horizontal;
}
return null;
}
/// Returns the [AxisDirection] in which reading occurs in the given [TextDirection].
......@@ -226,6 +229,7 @@ AxisDirection textDirectionToAxisDirection(TextDirection textDirection) {
case TextDirection.ltr:
return AxisDirection.right;
}
return null;
}
/// Returns the opposite of the given [AxisDirection].
......@@ -249,6 +253,7 @@ AxisDirection flipAxisDirection(AxisDirection axisDirection) {
case AxisDirection.left:
return AxisDirection.right;
}
return null;
}
/// Returns whether traveling along the given axis direction visits coordinates
......@@ -266,4 +271,5 @@ bool axisDirectionIsReversed(AxisDirection axisDirection) {
case AxisDirection.right:
return false;
}
return null;
}
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:typed_data' show Uint8List;
import 'dart:ui' as ui show instantiateImageCodec, Codec;
......@@ -22,12 +23,14 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
super.initInstances();
_instance = this;
_imageCache = createImageCache();
shaderWarmUp?.execute();
if (shaderWarmUp != null) {
shaderWarmUp.execute();
}
}
/// The current [PaintingBinding], if one has been created.
static PaintingBinding? get instance => _instance;
static PaintingBinding? _instance;
static PaintingBinding get instance => _instance;
static PaintingBinding _instance;
/// [ShaderWarmUp] to be executed during [initInstances].
///
......@@ -50,7 +53,7 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// See also:
///
/// * [ShaderWarmUp], the interface of how this warm up works.
static ShaderWarmUp? shaderWarmUp = const DefaultShaderWarmUp();
static ShaderWarmUp shaderWarmUp = const DefaultShaderWarmUp();
/// The singleton that implements the Flutter framework's image cache.
///
......@@ -59,8 +62,8 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
///
/// The image cache is created during startup by the [createImageCache]
/// method.
ImageCache? get imageCache => _imageCache;
ImageCache? _imageCache;
ImageCache get imageCache => _imageCache;
ImageCache _imageCache;
/// Creates the [ImageCache] singleton (accessible via [imageCache]).
///
......@@ -87,8 +90,8 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// above its native resolution should prefer scaling the canvas the image is
/// drawn into.
Future<ui.Codec> instantiateImageCodec(Uint8List bytes, {
int? cacheWidth,
int? cacheHeight,
int cacheWidth,
int cacheHeight,
bool allowUpscaling = false,
}) {
assert(cacheWidth == null || cacheWidth > 0);
......@@ -105,8 +108,8 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
@override
void evict(String asset) {
super.evict(asset);
imageCache!.clear();
imageCache!.clearLiveImages();
imageCache.clear();
imageCache.clearLiveImages();
}
@override
......@@ -167,4 +170,4 @@ class _SystemFontsNotifier extends Listenable {
///
/// The image cache is created during startup by the [PaintingBinding]'s
/// [PaintingBinding.createImageCache] method.
ImageCache? get imageCache => PaintingBinding.instance!.imageCache;
ImageCache get imageCache => PaintingBinding.instance.imageCache;
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'dart:ui' show Color, lerpDouble, hashValues;
......@@ -9,7 +10,7 @@ import 'dart:ui' show Color, lerpDouble, hashValues;
import 'package:flutter/foundation.dart';
double _getHue(double red, double green, double blue, double max, double delta) {
late double hue;
double hue;
if (max == 0.0) {
hue = 0.0;
} else if (max == red) {
......@@ -198,19 +199,19 @@ class HSVColor {
/// {@macro dart.ui.shadow.lerp}
///
/// Values outside of the valid range for each channel will be clamped.
static HSVColor? lerp(HSVColor? a, HSVColor? b, double t) {
static HSVColor lerp(HSVColor a, HSVColor b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return b!._scaleAlpha(t);
return b._scaleAlpha(t);
if (b == null)
return a._scaleAlpha(1.0 - t);
return HSVColor.fromAHSV(
lerpDouble(a.alpha, b.alpha, t)!.clamp(0.0, 1.0) as double,
lerpDouble(a.hue, b.hue, t)! % 360.0,
lerpDouble(a.saturation, b.saturation, t)!.clamp(0.0, 1.0) as double,
lerpDouble(a.value, b.value, t)!.clamp(0.0, 1.0) as double,
lerpDouble(a.alpha, b.alpha, t).clamp(0.0, 1.0) as double,
lerpDouble(a.hue, b.hue, t) % 360.0,
lerpDouble(a.saturation, b.saturation, t).clamp(0.0, 1.0) as double,
lerpDouble(a.value, b.value, t).clamp(0.0, 1.0) as double,
);
}
......@@ -382,19 +383,19 @@ class HSLColor {
///
/// Values for `t` are usually obtained from an [Animation<double>], such as
/// an [AnimationController].
static HSLColor? lerp(HSLColor? a, HSLColor? b, double t) {
static HSLColor lerp(HSLColor a, HSLColor b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return b!._scaleAlpha(t);
return b._scaleAlpha(t);
if (b == null)
return a._scaleAlpha(1.0 - t);
return HSLColor.fromAHSL(
lerpDouble(a.alpha, b.alpha, t)!.clamp(0.0, 1.0) as double,
lerpDouble(a.hue, b.hue, t)! % 360.0,
lerpDouble(a.saturation, b.saturation, t)!.clamp(0.0, 1.0) as double,
lerpDouble(a.lightness, b.lightness, t)!.clamp(0.0, 1.0) as double,
lerpDouble(a.alpha, b.alpha, t).clamp(0.0, 1.0) as double,
lerpDouble(a.hue, b.hue, t) % 360.0,
lerpDouble(a.saturation, b.saturation, t).clamp(0.0, 1.0) as double,
lerpDouble(a.lightness, b.lightness, t).clamp(0.0, 1.0) as double,
);
}
......@@ -440,7 +441,7 @@ class ColorSwatch<T> extends Color {
final Map<T, Color> _swatch;
/// Returns an element of the swatch table.
Color? operator [](T index) => _swatch[index];
Color operator [](T index) => _swatch[index];
@override
bool operator ==(Object other) {
......@@ -467,9 +468,9 @@ class ColorProperty extends DiagnosticsProperty<Color> {
/// The [showName], [style], and [level] arguments must not be null.
ColorProperty(
String name,
Color? value, {
Color value, {
bool showName = true,
Object? defaultValue = kNoDefaultValue,
Object defaultValue = kNoDefaultValue,
DiagnosticsTreeStyle style = DiagnosticsTreeStyle.singleLine,
DiagnosticLevel level = DiagnosticLevel.info,
}) : assert(showName != null),
......@@ -483,14 +484,14 @@ class ColorProperty extends DiagnosticsProperty<Color> {
);
@override
Map<String, Object?> toJsonMap(DiagnosticsSerializationDelegate delegate) {
final Map<String, Object?> json = super.toJsonMap(delegate);
Map<String, Object> toJsonMap(DiagnosticsSerializationDelegate delegate) {
final Map<String, Object> json = super.toJsonMap(delegate);
if (value != null) {
json['valueProperties'] = <String, Object>{
'red': value!.red,
'green': value!.green,
'blue': value!.blue,
'alpha': value!.alpha,
'red': value.red,
'green': value.green,
'blue': value.blue,
'alpha': value.alpha,
};
}
return json;
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:io';
import 'dart:ui' show Size, hashValues;
......@@ -29,7 +30,7 @@ typedef HttpClientProvider = HttpClient Function();
/// a mock client that hasn't been affected by other tests.
///
/// This value is ignored in non-debug builds.
HttpClientProvider? debugNetworkImageHttpClientProvider;
HttpClientProvider debugNetworkImageHttpClientProvider;
typedef PaintImageCallback = void Function(ImageSizeInfo);
......@@ -43,20 +44,20 @@ class ImageSizeInfo {
/// This class is used by the framework when it paints an image to a canvas
/// to report to `dart:developer`'s [postEvent], as well as to the
/// [debugOnPaintImage] callback if it is set.
const ImageSizeInfo({this.source, this.displaySize, required this.imageSize});
const ImageSizeInfo({this.source, this.displaySize, this.imageSize});
/// A unique identifier for this image, for example its asset path or network
/// URL.
final String? source;
final String source;
/// The size of the area the image will be rendered in.
final Size? displaySize;
final Size displaySize;
/// The size the image has been decoded to.
final Size imageSize;
/// The number of bytes needed to render the image without scaling it.
int get displaySizeInBytes => _sizeToBytes(displaySize!);
int get displaySizeInBytes => _sizeToBytes(displaySize);
/// The number of bytes used by the image in memory.
int get decodedSizeInBytes => _sizeToBytes(imageSize);
......@@ -68,15 +69,14 @@ class ImageSizeInfo {
}
/// Returns a JSON encodable representation of this object.
Map<String, Object?> toJson() {
return <String, Object?>{
Map<String, Object> toJson() {
return <String, Object>{
'source': source,
if (displaySize != null)
'displaySize': <String, Object?>{
'width': displaySize!.width,
'height': displaySize!.height,
},
'imageSize': <String, Object?>{
'displaySize': <String, double>{
'width': displaySize.width,
'height': displaySize.height,
},
'imageSize': <String, double>{
'width': imageSize.width,
'height': imageSize.height,
},
......@@ -125,7 +125,7 @@ class ImageSizeInfo {
/// a higher resolution while animating, but it would be problematic to have
/// a grid or list of such thumbnails all be at the full resolution at the same
/// time.
PaintImageCallback? debugOnPaintImage;
PaintImageCallback debugOnPaintImage;
/// If true, the framework will color invert and horizontally flip images that
/// have been decoded to a size taking at least [debugImageOverheadAllowance]
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:developer';
import 'dart:ui' show hashValues;
......@@ -102,7 +103,7 @@ class ImageCache {
assert(value >= 0);
if (value == maximumSize)
return;
TimelineTask? timelineTask;
TimelineTask timelineTask;
if (!kReleaseMode) {
timelineTask = TimelineTask()..start(
'ImageCache.setMaximumSize',
......@@ -116,7 +117,7 @@ class ImageCache {
_checkCacheSize(timelineTask);
}
if (!kReleaseMode) {
timelineTask!.finish();
timelineTask.finish();
}
}
......@@ -141,7 +142,7 @@ class ImageCache {
assert(value >= 0);
if (value == _maximumSizeBytes)
return;
TimelineTask? timelineTask;
TimelineTask timelineTask;
if (!kReleaseMode) {
timelineTask = TimelineTask()..start(
'ImageCache.setMaximumSizeBytes',
......@@ -155,7 +156,7 @@ class ImageCache {
_checkCacheSize(timelineTask);
}
if (!kReleaseMode) {
timelineTask!.finish();
timelineTask.finish();
}
}
......@@ -238,10 +239,10 @@ class ImageCache {
// will never complete, e.g. it was loaded in a FakeAsync zone.
// In such a case, we need to make sure subsequent calls to
// putIfAbsent don't return this image that may never complete.
final _LiveImage? image = _liveImages.remove(key);
final _LiveImage image = _liveImages.remove(key);
image?.removeListener();
}
final _PendingImage? pendingImage = _pendingImages.remove(key);
final _PendingImage pendingImage = _pendingImages.remove(key);
if (pendingImage != null) {
if (!kReleaseMode) {
Timeline.instantSync('ImageCache.evict', arguments: <String, dynamic>{
......@@ -251,7 +252,7 @@ class ImageCache {
pendingImage.removeListener();
return true;
}
final _CachedImage? image = _cache.remove(key);
final _CachedImage image = _cache.remove(key);
if (image != null) {
if (!kReleaseMode) {
Timeline.instantSync('ImageCache.evict', arguments: <String, dynamic>{
......@@ -259,7 +260,7 @@ class ImageCache {
'sizeInBytes': image.sizeBytes,
});
}
_currentSizeBytes -= image.sizeBytes!;
_currentSizeBytes -= image.sizeBytes;
return true;
}
if (!kReleaseMode) {
......@@ -275,13 +276,13 @@ class ImageCache {
///
/// Resizes the cache as appropriate to maintain the constraints of
/// [maximumSize] and [maximumSizeBytes].
void _touch(Object key, _CachedImage image, TimelineTask? timelineTask) {
void _touch(Object key, _CachedImage image, TimelineTask timelineTask) {
// TODO(dnfield): Some customers test in release mode with asserts enabled.
// This is bound to cause problems, b/150295238 is tracking that. For now,
// avoid this being a point of failure.
assert(kReleaseMode || timelineTask != null);
if (image.sizeBytes != null && image.sizeBytes! <= maximumSizeBytes) {
_currentSizeBytes += image.sizeBytes!;
if (image.sizeBytes != null && image.sizeBytes <= maximumSizeBytes) {
_currentSizeBytes += image.sizeBytes;
_cache[key] = image;
_checkCacheSize(timelineTask);
}
......@@ -309,11 +310,11 @@ class ImageCache {
/// `onError` is also provided. When an exception is caught resolving an image,
/// no completers are cached and `null` is returned instead of a new
/// completer.
ImageStreamCompleter? putIfAbsent(Object key, ImageStreamCompleter loader(), { ImageErrorListener? onError }) {
ImageStreamCompleter putIfAbsent(Object key, ImageStreamCompleter loader(), { ImageErrorListener onError }) {
assert(key != null);
assert(loader != null);
TimelineTask? timelineTask;
TimelineTask? listenerTask;
TimelineTask timelineTask;
TimelineTask listenerTask;
if (!kReleaseMode) {
timelineTask = TimelineTask()..start(
'ImageCache.putIfAbsent',
......@@ -322,11 +323,11 @@ class ImageCache {
},
);
}
ImageStreamCompleter? result = _pendingImages[key]?.completer;
ImageStreamCompleter result = _pendingImages[key]?.completer;
// Nothing needs to be done because the image hasn't loaded yet.
if (result != null) {
if (!kReleaseMode) {
timelineTask!.finish(arguments: <String, dynamic>{'result': 'pending'});
timelineTask.finish(arguments: <String, dynamic>{'result': 'pending'});
}
return result;
}
......@@ -334,10 +335,10 @@ class ImageCache {
// recently used position below.
// Don't use _touch here, which would trigger a check on cache size that is
// not needed since this is just moving an existing cache entry to the head.
final _CachedImage? image = _cache.remove(key);
final _CachedImage image = _cache.remove(key);
if (image != null) {
if (!kReleaseMode) {
timelineTask!.finish(arguments: <String, dynamic>{'result': 'keepAlive'});
timelineTask.finish(arguments: <String, dynamic>{'result': 'keepAlive'});
}
// The image might have been keptAlive but had no listeners (so not live).
// Make sure the cache starts tracking it as live again.
......@@ -346,11 +347,11 @@ class ImageCache {
return image.completer;
}
final _CachedImage? liveImage = _liveImages[key];
final _CachedImage liveImage = _liveImages[key];
if (liveImage != null) {
_touch(key, liveImage, timelineTask);
if (!kReleaseMode) {
timelineTask!.finish(arguments: <String, dynamic>{'result': 'keepAlive'});
timelineTask.finish(arguments: <String, dynamic>{'result': 'keepAlive'});
}
return liveImage.completer;
}
......@@ -360,7 +361,7 @@ class ImageCache {
_trackLiveImage(key, _LiveImage(result, null, () => _liveImages.remove(key)));
} catch (error, stackTrace) {
if (!kReleaseMode) {
timelineTask!.finish(arguments: <String, dynamic>{
timelineTask.finish(arguments: <String, dynamic>{
'result': 'error',
'error': error.toString(),
'stackTrace': stackTrace.toString(),
......@@ -386,12 +387,12 @@ class ImageCache {
// will have to listen to the image at least once so we don't leak it in
// the live image tracking.
// If the cache is disabled, this variable will be set.
_PendingImage? untrackedPendingImage;
void listener(ImageInfo? info, bool syncCall) {
_PendingImage untrackedPendingImage;
void listener(ImageInfo info, bool syncCall) {
// Images that fail to load don't contribute to cache size.
final int imageSize = info == null || info.image == null ? 0 : info.image.height * info.image.width * 4;
final int imageSize = info?.image == null ? 0 : info.image.height * info.image.width * 4;
final _CachedImage image = _CachedImage(result!, imageSize);
final _CachedImage image = _CachedImage(result, imageSize);
_trackLiveImage(
key,
......@@ -402,7 +403,7 @@ class ImageCache {
),
);
final _PendingImage? pendingImage = untrackedPendingImage ?? _pendingImages.remove(key);
final _PendingImage pendingImage = untrackedPendingImage ?? _pendingImages.remove(key);
if (pendingImage != null) {
pendingImage.removeListener();
}
......@@ -412,11 +413,11 @@ class ImageCache {
}
if (!kReleaseMode && !listenedOnce) {
listenerTask!.finish(arguments: <String, dynamic>{
listenerTask.finish(arguments: <String, dynamic>{
'syncCall': syncCall,
'sizeInBytes': imageSize,
});
timelineTask!.finish(arguments: <String, dynamic>{
timelineTask.finish(arguments: <String, dynamic>{
'currentSizeBytes': currentSizeBytes,
'currentSize': currentSize,
});
......@@ -480,9 +481,9 @@ class ImageCache {
// Remove images from the cache until both the length and bytes are below
// maximum, or the cache is empty.
void _checkCacheSize(TimelineTask? timelineTask) {
void _checkCacheSize(TimelineTask timelineTask) {
final Map<String, dynamic> finishArgs = <String, dynamic>{};
TimelineTask? checkCacheTask;
TimelineTask checkCacheTask;
if (!kReleaseMode) {
checkCacheTask = TimelineTask(parent: timelineTask)..start('checkCacheSize');
finishArgs['evictedKeys'] = <String>[];
......@@ -491,8 +492,8 @@ class ImageCache {
}
while (_currentSizeBytes > _maximumSizeBytes || _cache.length > _maximumSize) {
final Object key = _cache.keys.first;
final _CachedImage image = _cache[key]!;
_currentSizeBytes -= image.sizeBytes!;
final _CachedImage image = _cache[key];
_currentSizeBytes -= image.sizeBytes;
_cache.remove(key);
if (!kReleaseMode) {
finishArgs['evictedKeys'].add(key.toString());
......@@ -501,7 +502,7 @@ class ImageCache {
if (!kReleaseMode) {
finishArgs['endSize'] = currentSize;
finishArgs['endSizeBytes'] = currentSizeBytes;
checkCacheTask!.finish(arguments: finishArgs);
checkCacheTask.finish(arguments: finishArgs);
}
assert(_currentSizeBytes >= 0);
assert(_cache.length <= maximumSize);
......@@ -584,11 +585,11 @@ class _CachedImage {
_CachedImage(this.completer, this.sizeBytes);
final ImageStreamCompleter completer;
int? sizeBytes;
int sizeBytes;
}
class _LiveImage extends _CachedImage {
_LiveImage(ImageStreamCompleter completer, int? sizeBytes, this.handleRemove)
_LiveImage(ImageStreamCompleter completer, int sizeBytes, this.handleRemove)
: super(completer, sizeBytes);
final VoidCallback handleRemove;
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:developer';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment