Skip to content

Commit 89f0022

Browse files
committed
feat: Error handling enhancement for vector_graphics
- copy from this PR: dnfield/vector_graphics#258
1 parent 5e90ce2 commit 89f0022

1 file changed

Lines changed: 52 additions & 39 deletions

File tree

packages/vector_graphics/lib/src/vector_graphics.dart

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'dart:math' as math;
66
import 'dart:ui' as ui;
77

8+
import 'package:flutter/cupertino.dart';
89
import 'package:flutter/foundation.dart';
910
import 'package:flutter/widgets.dart';
1011
import 'package:vector_graphics_codec/vector_graphics_codec.dart';
@@ -279,8 +280,7 @@ class _PictureData {
279280

280281
@immutable
281282
class _PictureKey {
282-
const _PictureKey(
283-
this.cacheKey, this.locale, this.textDirection, this.clipViewbox);
283+
const _PictureKey(this.cacheKey, this.locale, this.textDirection, this.clipViewbox);
284284

285285
final Object cacheKey;
286286
final Locale? locale;
@@ -300,16 +300,14 @@ class _PictureKey {
300300
}
301301

302302
class _VectorGraphicWidgetState extends State<VectorGraphic> {
303-
_PictureData? _pictureInfo;
303+
_PictureData? _pictureData;
304304
Object? _error;
305305
StackTrace? _stackTrace;
306306
Locale? locale;
307307
TextDirection? textDirection;
308308

309-
static final Map<_PictureKey, _PictureData> _livePictureCache =
310-
<_PictureKey, _PictureData>{};
311-
static final Map<_PictureKey, Future<_PictureData>> _pendingPictures =
312-
<_PictureKey, Future<_PictureData>>{};
309+
static final Map<_PictureKey, _PictureData?> _livePictureCache = <_PictureKey, _PictureData?>{};
310+
static final Map<_PictureKey, Future<_PictureData?>> _pendingPictures = <_PictureKey, Future<_PictureData?>>{};
313311

314312
@override
315313
void didChangeDependencies() {
@@ -329,8 +327,8 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
329327

330328
@override
331329
void dispose() {
332-
_maybeReleasePicture(_pictureInfo);
333-
_pictureInfo = null;
330+
_maybeReleasePicture(_pictureData);
331+
_pictureData = null;
334332
super.dispose();
335333
}
336334

@@ -345,29 +343,39 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
345343
}
346344
}
347345

348-
Future<_PictureData> _loadPicture(
349-
BuildContext context, _PictureKey key, BytesLoader loader) {
346+
Future<_PictureData?> _loadPicture(BuildContext context, _PictureKey key, BytesLoader loader) {
350347
if (_pendingPictures.containsKey(key)) {
351348
return _pendingPictures[key]!;
352349
}
353-
final Future<_PictureData> result =
354-
loader.loadBytes(context).then((ByteData data) {
355-
return decodeVectorGraphics(
356-
data,
357-
locale: key.locale,
358-
textDirection: key.textDirection,
359-
clipViewbox: key.clipViewbox,
360-
loader: loader,
361-
onError: (Object error, StackTrace? stackTrace) {
362-
return _handleError(
363-
error,
364-
stackTrace,
365-
);
366-
},
367-
);
368-
}).then((PictureInfo pictureInfo) {
369-
return _PictureData(pictureInfo, 0, key);
350+
351+
final Future<_PictureData?> result = loader.loadBytes(context).then((ByteData data) async {
352+
if (data.lengthInBytes == 0) {
353+
debugPrint('_VectorGraphicWidgetState.decodeVectorGraphics: empty');
354+
_handleError(const FormatException('Empty SVG xml content'), null);
355+
return null;
356+
} else {
357+
return decodeVectorGraphics(data,
358+
locale: key.locale,
359+
textDirection: key.textDirection,
360+
clipViewbox: key.clipViewbox,
361+
loader: loader, onError: (Object error, StackTrace? stackTrace) {
362+
debugPrintStack(
363+
stackTrace: stackTrace, label: '_VectorGraphicWidgetState.decodeVectorGraphics.onError: $error');
364+
_handleError(error, stackTrace);
365+
});
366+
}
367+
}).onError((Object? error, StackTrace stackTrace) {
368+
debugPrintStack(stackTrace: stackTrace, label: '_VectorGraphicWidgetState._loadPictureInfo.onError: $error');
369+
_handleError(error ?? '', stackTrace);
370+
return null;
371+
}).then((PictureInfo? pictureInfo) {
372+
if (pictureInfo == null) {
373+
return null;
374+
} else {
375+
return _PictureData(pictureInfo, 0, key);
376+
}
370377
});
378+
371379
_pendingPictures[key] = result;
372380
result.whenComplete(() {
373381
_pendingPictures.remove(key);
@@ -376,6 +384,9 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
376384
}
377385

378386
void _handleError(Object error, StackTrace? stackTrace) {
387+
if (!mounted) {
388+
return;
389+
}
379390
setState(() {
380391
_error = error;
381392
_stackTrace = stackTrace;
@@ -385,20 +396,22 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
385396
void _loadAssetBytes() {
386397
// First check if we have an avilable picture and use this immediately.
387398
final Object loaderKey = widget.loader.cacheKey(context);
388-
final _PictureKey key =
389-
_PictureKey(loaderKey, locale, textDirection, widget.clipViewbox);
399+
final _PictureKey key = _PictureKey(loaderKey, locale, textDirection, widget.clipViewbox);
390400
final _PictureData? data = _livePictureCache[key];
391401
if (data != null) {
392402
data.count += 1;
393403
setState(() {
394-
_maybeReleasePicture(_pictureInfo);
395-
_pictureInfo = data;
404+
_maybeReleasePicture(_pictureData);
405+
_pictureData = data;
396406
});
397407
return;
398408
}
399409
// If not, then check if there is a pending load.
400410
final BytesLoader loader = widget.loader;
401-
_loadPicture(context, key, loader).then((_PictureData data) {
411+
_loadPicture(context, key, loader).then((_PictureData? data) {
412+
if (data == null) {
413+
return;
414+
}
402415
data.count += 1;
403416

404417
// The widget may have changed, requesting a new vector graphic before
@@ -411,8 +424,8 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
411424
_livePictureCache[key] = data;
412425
}
413426
setState(() {
414-
_maybeReleasePicture(_pictureInfo);
415-
_pictureInfo = data;
427+
_maybeReleasePicture(_pictureData);
428+
_pictureData = data;
416429
});
417430
});
418431
}
@@ -421,7 +434,7 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
421434

422435
@override
423436
Widget build(BuildContext context) {
424-
final PictureInfo? pictureInfo = _pictureInfo?.pictureInfo;
437+
final PictureInfo? pictureInfo = _pictureData?.pictureInfo;
425438

426439
Widget child;
427440
if (pictureInfo != null) {
@@ -452,22 +465,22 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
452465
if (_webRenderObject) {
453466
child = _RawWebVectorGraphicWidget(
454467
pictureInfo: pictureInfo,
455-
assetKey: _pictureInfo!.key,
468+
assetKey: _pictureData!.key,
456469
colorFilter: widget.colorFilter,
457470
opacity: widget.opacity,
458471
);
459472
} else if (widget.strategy == RenderingStrategy.raster) {
460473
child = _RawVectorGraphicWidget(
461474
pictureInfo: pictureInfo,
462-
assetKey: _pictureInfo!.key,
475+
assetKey: _pictureData!.key,
463476
colorFilter: widget.colorFilter,
464477
opacity: widget.opacity,
465478
scale: scale,
466479
);
467480
} else {
468481
child = _RawPictureVectorGraphicWidget(
469482
pictureInfo: pictureInfo,
470-
assetKey: _pictureInfo!.key,
483+
assetKey: _pictureData!.key,
471484
colorFilter: widget.colorFilter,
472485
opacity: widget.opacity,
473486
);

0 commit comments

Comments
 (0)