perf(images): size decoded covers from layout constraints

This commit is contained in:
zarzet
2026-09-06 02:33:42 +07:00
parent fdb4a0eaa5
commit 1d0bb56f9b
2 changed files with 73 additions and 2 deletions
+30 -2
View File
@@ -41,10 +41,38 @@ class CachedCoverImage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final autoMemCacheWidth =
if (width != null ||
height != null ||
memCacheWidth != null ||
memCacheHeight != null) {
return _buildImage(context, const BoxConstraints());
}
// Grid cells size their children through constraints rather than explicit
// width/height. Use those bounds for decoding as well as explicit sizes.
return LayoutBuilder(
builder: (context, constraints) => _buildImage(context, constraints),
);
}
Widget _buildImage(BuildContext context, BoxConstraints constraints) {
var autoMemCacheWidth =
memCacheWidth ?? _cacheExtentForLogicalSize(context, width);
final autoMemCacheHeight =
var autoMemCacheHeight =
memCacheHeight ?? _cacheExtentForLogicalSize(context, height);
if (autoMemCacheWidth == null && autoMemCacheHeight == null) {
// Infer one axis to preserve the source aspect ratio and respect any
// explicit decode override used by large artwork/header consumers.
autoMemCacheWidth = _cacheExtentForLogicalSize(
context,
constraints.maxWidth,
);
if (autoMemCacheWidth == null) {
autoMemCacheHeight = _cacheExtentForLogicalSize(
context,
constraints.maxHeight,
);
}
}
final diskCacheWidth = resizeDiskCache ? autoMemCacheWidth : null;
final diskCacheHeight = resizeDiskCache ? autoMemCacheHeight : null;
final image = CachedNetworkImage(
+43
View File
@@ -0,0 +1,43 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:spotiflac_android/widgets/cached_cover_image.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
for (final explicit in [false, true]) {
testWidgets(
'grid decode follows constraints, explicit override=$explicit',
(tester) async {
await tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: const MediaQueryData(devicePixelRatio: 2),
child: Center(
child: SizedBox.square(
dimension: 180,
child: CachedCoverImage(
imageUrl: 'https://example.invalid/cover.png',
memCacheWidth: explicit ? 1200 : null,
errorWidget: (_, _, _) => const SizedBox(),
),
),
),
),
),
);
final image = tester.widget<CachedNetworkImage>(
find.byType(CachedNetworkImage),
);
expect(image.memCacheWidth, explicit ? 1200 : 360);
expect(image.memCacheHeight, isNull);
expect(image.maxWidthDiskCache, isNull);
expect(
tester.getSize(find.byType(CachedCoverImage)),
const Size(180, 180),
);
await tester.pumpWidget(const SizedBox());
},
);
}
}