Фликеры hero в связке с cached_network_image

У меня есть список спикеров, при нажатии на любой из элементов я перехожу на страницу с деталями об этом спикере. При переходе маленький аватар превращается в большой, с помощью Hero виджета. Данные аватары - это CachedNetworkImage. В нормальном состоянии (когда изображение успешно загружается из сети) все работает отлично. Но, если смоделировать ситуацию, когда изображение не загружается, или возникает другая ошибка, то errorWidget у CachedNetworkImage, начинает мерцать при переходе.

Гифка как это сейчас выглядит: https://imgur.com/a/E7ogQhV

(Извините за неудобную ссылку, просто не могу загрузить гифку через сайт почему-то)

Я пробовал зафетчить картинку самостоятельно, и в зависимости от кода ответа, выбирать: отображать виджет для плейсхолдера или CachedNetworkImage, но, возникло другое поведение, при котором, в случае уже успешной загрузки изображения, отображался в начале виджет плейсхолдер

class NetworkImageWidget extends StatefulWidget {
  const NetworkImageWidget({
    super.key,
    required this.imageUrl,
    this.width,
    this.height,
    this.fit = BoxFit.cover,
  });

  final String? imageUrl;
  final double? width;
  final double? height;
  final BoxFit? fit;

  @override
  State<NetworkImageWidget> createState() => _NetworkImageWidgetState();
}

class _NetworkImageWidgetState extends State<NetworkImageWidget> {
  @override
  void initState() {
    super.initState();
    // fetchImage();
  }

  bool isImageReal = false;

  bool get _isImageInvalid =>
      (widget.imageUrl?.isEmpty ?? true) ||
      (!widget.imageUrl!.startsWith('http') || !isImageReal);

  // Future<void> fetchImage() async {
  //
  //   final response = await http.get(Uri.parse(widget.imageUrl!));
  //   if (response.statusCode == 200) {
  //     setState(() => isImageReal = true);
  //   } else {
  //     setState(() => isImageReal = false);
  //   }
  // }

  @override
  Widget build(BuildContext context) {
    // if (_isImageInvalid) {
    //   return _PlaceHolderImageWidget(
    //     width: widget.width,
    //     height: widget.height,
    //     fit: widget.fit,
    //   );
    // }

    return CachedNetworkImage(
      imageUrl: widget.imageUrl!,
      width: widget.width,
      height: widget.height,
      fit: widget.fit,
      // cacheManager: CacheManager,
      placeholder: (_, __) => _CircleImageShimmer(
        width: widget.width,
        height: widget.height,
      ),
      errorWidget: (_, __, ___) => _PlaceHolderImageWidget(
        width: widget.width,
        height: widget.height,
        fit: widget.fit,
      ),
    );
  }
}

class _CircleImageShimmer extends StatelessWidget {
  const _CircleImageShimmer({
    required this.width,
    required this.height,
  });

  final double? width;
  final double? height;

  @override
  Widget build(BuildContext context) {
    final appColor = AppColorScheme.of(context);
    return Shimmer.fromColors(
      baseColor: appColor.shimmer,
      highlightColor: appColor.shimmerHighlight,
      child: Container(
        color: Colors.white,
        width: width,
        height: height,
      ),
    );
  }
}

class _PlaceHolderImageWidget extends StatelessWidget {
  const _PlaceHolderImageWidget({this.width, this.height, this.fit});

  final double? width;
  final double? height;
  final BoxFit? fit;

  @override
  Widget build(BuildContext context) => Image.asset(
        Images.largePlaceholder,
        width: width,
        height: height,
        fit: fit,
      );
}

Это код моего виджета для CachedNetworkImage, который я затем оборачиваю в Hero виджет


Ответы (0 шт):