CachedNetwork Image - No host specified in URI

1,469

Solution 1

Maybe you can do something like this. Create two CacheNetworkImage based on your url. One is for null, another is for not null.

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

Solution 2

You shouldn't be creating a CachedNetworkImage at all if you don't have an image to load.

One way to do that:

  @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) => Container(),
                  errorWidget: (context, url, error) => fallback,
                  ...

A hacky alternative would be to just provide a non-routable URL which would be guaranteed to fail (e.g. https://0.0.0.0/).

Share:
1,469
Amxela
Author by

Amxela

Updated on January 02, 2023

Comments

  • Amxela
    Amxela over 1 year

    I'm using a cached network image to load in an image from firebase and if the image is URL is null it loads a circle avatar with an icon in it.

    It works fine in the emulator but it always posts the error when image url is null:

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

    when image url is not null:

    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)
    <asynchronous suspension>
    #6      WebHelper._downloadOrAddToQueue (package:flutter_cache_manager/src/web/web_helper.dart:67:7)
    <asynchronous suspension>
    
    Image provider: CachedNetworkImageProvider("", scale: 1.0)
     Image key: CachedNetworkImageProvider("", scale: 1.0):
      CachedNetworkImageProvider("", scale: 1.0)
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    

    The UI shows exactly what it is suppose to though. image URL is not null image URL is null

    What can I do to fix this error from showing?

    Here's the code:

    class ProfilePicture extends GetView<UserController> {
      const ProfilePicture({
        Key? key,
        this.enabled = false,
      }) : super(key: key);
    
      final bool enabled;
    
      double get radius => 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) => 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(
                          () => 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: (_) => const ImagePickerBottomModal(),
                    );
                  } else {
                    Get.to(
                      const ProfileScreen(),
                      routeName: AppRoutes.routeProfile,
                      curve: Curves.fastOutSlowIn,
                      transition: Transition.downToUp,
                    );
                  }
                },
              ),
            );
          },
        );
      }
    }
    
  • Amxela
    Amxela over 2 years
    This doesn't quite work because CachedNetworkImage always needs an image URL. I tried with just Circle Avatars instead and it gives me the same error. The CachedNetworkImage was a try at fixing this.
  • John Joe
    John Joe over 2 years
    You got the point too. How about create a container widget and put the circleAvatar as the child? I think the errorWidget only used for wrong url, not for null.