Как правильно загружать изображения в Flutter и обрабатывать исключения при загрузке

#flutter

#flutter

Вопрос:

Я хотел бы знать, как правильно загружать изображения с устройства и обрабатывать исключения, если изображение отсутствует или повреждено. Пользователь выбирает изображение с устройства, и я хочу его открыть. Я использую изображение позже в своем коде, поэтому мне недостаточно просто показать его в каком-нибудь виджете. В настоящее время я использую следующий код, который в большинстве случаев работает нормально:

   Future<ui.Image> imageLoadFromDevice(String path) async {

    await askPermissionForStorage();

    ImageProvider imageProvider = FileImage (  File ( path ), scale: 1 );

    Completer<ImageInfo> completer = Completer();
    imageProvider.resolve(ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info, bool _) {
      completer.complete(info);
    }));

    ImageInfo imageInfo = await completer.future;

    return imageInfo.image;
  }
  

Но если изображение отсутствует или повреждено, в консоли отображается сообщение «Исключение, перехваченное службой ресурсов изображений», но мой перехватчик исключений над этой функцией не получает исключения.

  1. Правильно ли я загружаю изображение или есть лучший способ?
  2. В случае, если этот код в порядке, как мне перехватывать исключения, в частности, отсутствующий файл или поврежденное изображение?

Ответ №1:

Я не уверен насчет поврежденных изображений, но в случае отсутствия файлов вы можете сохранить File(path) их в переменной и использовать varname.exists() для проверки перед настройкой вашего ImageProvider.

Комментарии:

1. Спасибо, я знаком с File(path).exists() . В этом случае это определенно возможно. Но в случаях race / edge все еще существует вероятность того, что «exists» вернет true, тогда файл будет чем-то удален, и я бы попытался открыть отсутствующий файл. Поэтому мне нужно получить исключение в этом случае. Но этот код просто выводится в консоль: «Исключение, обнаруженное службой ресурсов изображений. Не удается открыть file, path = …», но исключения нет, поэтому я не могу его поймать.

Ответ №2:

Хороший вопрос! 🙂

Вы можете использовать более простой код ниже, который загружает изображение так, как вы хотите.

 import 'dart:ui' as ui;

  Future<ui.Image> imageLoadFromDevice(String path) async {

    await askPermissionForStorage();

    File fileImage = File(path);
    final Uint8List imageUint8List =  await fileImage.readAsBytes();
    final ui.Codec codec = await ui.instantiateImageCodec(imageUint8List);
    final ui.FrameInfo frameInfo = await codec.getNextFrame();

    return frameInfo.image;
  }
  

Чтобы перехватить исключения из этого кода, вы можете поместить его в try-catch. Любое исключение при загрузке изображения должно создавать общее исключение, которое можно перехватить и обработать.

Ответ №3:

Для обработки ошибок из an ImageStream используйте onError аргумент ImageStreamListener конструктора:

 imageProvider.resolve(ImageConfiguration()).addListener(ImageStreamListener(
  (ImageInfo info, bool _) { }, // called for success
  onError: (Object error, StackTrace? stackTrace) { }, // called for error
));