Образ кэшированной сети — В URI не указан хост

#flutter #flutter-layout

#трепетать #флаттер-макет

Вопрос:

Я использую кэшированное сетевое изображение для загрузки изображения из firebase, и если URL-адрес изображения равен нулю, он загружает аватар круга со значком в нем.

Он отлично работает в эмуляторе, но всегда выдает ошибку, когда URL-адрес изображения равен нулю:

 I/flutter ( 6907): CacheManager: Failed to download file from with error: I/flutter ( 6907): Invalid argument(s): No host specified in URI   

когда URL-адрес изображения не равен нулю:

 I/flutter ( 6907): CacheManager: Failed to download file from with error: I/flutter ( 6907): Invalid argument(s): No host specified in URI   ══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞════════════════════════════════════════════════════ The following ArgumentError was thrown resolving an image codec: Invalid argument(s): No host specified in URI  When the exception was thrown, this was the stack: #0 _HttpClient._openUrl (dart:_http/http_impl.dart:2662:9) #1 _HttpClient.openUrl (dart:_http/http_impl.dart:2568:7) #2 IOClient.send (package:http/src/io_client.dart:35:38) #3 HttpFileService.get (package:flutter_cache_manager/src/web/file_service.dart:35:44) #4 WebHelper._download (package:flutter_cache_manager/src/web/web_helper.dart:117:24) #5 WebHelper._updateFile (package:flutter_cache_manager/src/web/web_helper.dart:99:28) lt;asynchronous suspensiongt; #6 WebHelper._downloadOrAddToQueue (package:flutter_cache_manager/src/web/web_helper.dart:67:7) lt;asynchronous suspensiongt;  Image provider: CachedNetworkImageProvider("", scale: 1.0)  Image key: CachedNetworkImageProvider("", scale: 1.0):  CachedNetworkImageProvider("", scale: 1.0) ════════════════════════════════════════════════════════════════════════════════════════════════════  

Пользовательский интерфейс показывает именно то, что он должен, хотя. URL-адрес изображения не является нулевым URL-адрес изображения равен нулю

Что я могу сделать, чтобы исправить эту ошибку?

Вот код:

 class ProfilePicture extends GetViewlt;UserControllergt; {  const ProfilePicture({  Key? key,  this.enabled = false,  }) : super(key: key);   final bool enabled;   double get radius =gt; enabled ? 40.0 : 30.0;   @override  Widget build(BuildContext context) {  return Obx(  () {  return Hero(  tag: 'profile_hero',  child: GestureDetector(  child: CachedNetworkImage(  imageUrl: controller.user?.photoURL ?? '',  placeholder: (context, url) =gt; Container(),  errorWidget: (context, url, error) {  return Stack(  children: [  CircleAvatar(  radius: radius,  backgroundColor: Get.theme.brightness == Brightness.dark  ? Colors.transparent  : Get.theme.scaffoldBackgroundColor,  child: Icon(Icons.person_outline_rounded,  size: radius * 1.5,  color: Get.theme.brightness == Brightness.dark  ? Colors.white  : primaryColor),  ),  Obx(  () =gt; Visibility(  visible: controller.loading.value,  child: SizedBox(  height: radius * 2,  width: radius * 2,  child: const CircularProgressIndicator(),  ),  ),  ),  ],  );  },  imageBuilder: (_, imageProvider) {  return Stack(  children: [  CircleAvatar(  radius: radius,  backgroundImage: imageProvider,  ),  Obx(() {  return Visibility(  visible: controller.loading.value,  child: SizedBox(  height: radius * 2,  width: radius * 2,  child: const CircularProgressIndicator(  strokeWidth: 5,  ),  ),  );  }),  ],  );  },  ),  onTap: () {  if (enabled) {  showModalBottomSheet(  context: context,  shape: RoundedRectangleBorder(  borderRadius: BorderRadius.circular(12.0),  ),  builder: (_) =gt; const ImagePickerBottomModal(),  );  } else {  Get.to(  const ProfileScreen(),  routeName: AppRoutes.routeProfile,  curve: Curves.fastOutSlowIn,  transition: Transition.downToUp,  );  }  },  ),  );  },  );  } }  

Ответ №1:

Может быть, ты сможешь сделать что-то подобное. Создайте два CacheNetworkImage на основе вашего URL-адреса. Один — для null, другой-для not null.

 child: (controller.user?.photoURL == null) ?  CacheNetworkImage ( // with CircleAvatar ) : CacheNetworkImage(// with image path)  

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

1. Это не совсем работает, потому что CachedNetworkImage всегда нуждается в URL-адресе изображения. Вместо этого я попробовал использовать только круговые аватары, и это дает мне ту же ошибку. Изображение CachedNetworkImage было попыткой исправить это.

2. Ты тоже уловил суть. Как насчет того, чтобы создать виджет-контейнер и поместить его в circleAvatar качестве дочернего элемента? Я думаю errorWidget , что используется только для неправильного URL, а не для null.

Ответ №2:

Вам вообще не следует создавать CachedNetworkImage , если у вас нет загружаемого изображения.

Один из способов сделать это:

 @override  Widget build(BuildContext context) {  var photoURL = controller.user?.photoURL;  var fallback = Stack(  children: [  CircleAvatar(...)  ],  );   return Obx(  () {  return Hero(  tag: 'profile_hero',  child: GestureDetector(  child: (photoURL == null)  ? fallback  : CachedNetworkImage(  imageUrl: photoURL,  placeholder: (context, url) =gt; Container(),  errorWidget: (context, url, error) =gt; fallback,  ...  

Хакерской альтернативой было бы просто предоставить не маршрутизируемый URL-адрес, который гарантированно завершится неудачей (например https://0.0.0.0/ ).