#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) ════════════════════════════════════════════════════════════════════════════════════════════════════
Пользовательский интерфейс показывает именно то, что он должен, хотя.
Что я могу сделать, чтобы исправить эту ошибку?
Вот код:
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/
).