Why are there irregularities in the loading speed of my cached images?

26 Views Asked by At

In developing my first "real" Flutter project I wanted to create an image carousel which fetches images from Firebase Storage. To accomplish this, I utilized both the carousel_slider package & the cached_network_image package. The logic is as follows:

Upon loading into the homepage, initState begins the process of fetching urls & caching the images to be used in the carousel.

 @override
  void initState() {
    super.initState();
    PrecacheImages precacher = PrecacheImages();
    precacher.getImageURLs().then((urls) {
      setState(() {
        imageURLs = urls;
      });
      precacher.awaitCacheComplete(context, urls);
    });
  }

Here is the PrecacheImages class that defines those processes:

class PrecacheImages {
  late List<String> imageURLs;

  Future<List<String>> getImageURLs() async {
    try {
      // Reference to the Firebase Storage folder
      Reference storageRef =
          FirebaseStorage.instance.ref().child('Production-Photos-Storage');

      // Get list of items (photos) in the folder
      final ListResult result = await storageRef.list();

      // Extract download URLs from each item (photo) in the list
      List<String> imageURLs = await Future.wait(
          result.items.map((item) => item.getDownloadURL()).toList());

      return imageURLs;
    } catch (e) {
      print(e);
      return [];
    }
  }

  Future awaitCacheComplete(
      BuildContext context, List<String> imageURLs) async {
    await Future.wait(
      //wait until all images are cached and downloaded
      imageURLs.map((urlImage) => cacheImage(context, urlImage)).toList(),
    );
  }

  Future cacheImage(BuildContext context, String urlImage) async {
    precacheImage(CachedNetworkImageProvider(urlImage), context);
  }
}

This is all accomplished in preparation for the user to press a button navigating them to SubmitPhotoView:

onPressed: () {
    Navigator.pushNamed(
    context,
    submitPhotoViewTabletRoute,
    arguments: imageURLs,
    );
   },

This way, all the images should be precached and ready for use in the image carousel:

final List<String> imageURLs = ModalRoute.of(context)!.settings.arguments as List<String>;
//access imageURLs from Navigator argument


CarouselSlider.builder(
        disableGesture: true,
        itemCount: imageURLs.length,
        options: CarouselOptions(
        autoPlay: true,
        height: 100.h,
        viewportFraction: .25,
        scrollPhysics: const NeverScrollableScrollPhysics(),
        autoPlayInterval: const Duration(seconds: 5),
        autoPlayAnimationDuration: const Duration(seconds: 5),
        autoPlayCurve: Curves.linear,
                       ),
                          itemBuilder: (context, index, realIdx) {
                            return Center(
                              child: CachedNetworkImage(
                                filterQuality: FilterQuality.medium,
                                imageUrl: imageURLs[index],
                                fit: BoxFit.cover,
                                width: 125.w,
                              ),
                            );
                          },
                        )

This works as intended only circumstantially. Upon a hot restart and waiting a little for the processes within initState to complete, pushing the Navigator button will result as intended: all the photos are immediately visible and the carousel commences its animations.

However, when I navigate back to the homepage and try to repeat the process, the images take their sweet time loading in no matter how long I wait before pressing the button. I understand it is the goal of the CarouselSlider.builder to only render the photos on-demand... however, I figure if it can work correctly once, it can do it again.

It is my understanding that once these images are stored in the cache, they remain there and should be ready for subsequent use by the carousel. So really, apart from the initial caching logic there should be nothing for the carousel to wait on except its own build process and that of the cached images.

Thanks for your help understanding what is going on here, any suggestions will definitely be appreciated. I will attach reference images to help you understand how the issue manifests.

PS - I am aware of the fast_cached_network_image package but have not explored that as an option as the package I'm currently using seems to be far more popular & comes from a verified developer.

Initial attempt

Retried

1

There are 1 best solutions below

2
FreakyAli On

Hot restart generally internally re-runs everything, Hot restart and Hot reload are only there to help you debug they do not represent real performance, you should test your app in release mode and see if these issues exist and I am pretty sure they won't. Debugging adds a lot of overhead and runtime compilations can get messy in debug mode.

I highly recommend you read about Hot Reload and Hot restart once it will help you understand things better

https://docs.flutter.dev/tools/hot-reload

There is also a summary of their understanding here What is the difference between hot reload, hot restart, and full restart?