skip to Main Content

I am using Google Maps Places API to find images of nearby places. However, I find it very inefficient and more expensive to constantly be reloading images I’ve already loaded in the past by making a request. I’ve noticed, however, that when I open the request link in my browser, I get redirected to another page that doesn’t take a request to open. How can I get this page so I only have to make a request once per image?
I’ve been told to cache the image, but I don’t see how this fixes any problem since all it does it store the request link. If this truly is an applicable method, an explanation would be greatly appreciated.

2

Answers


  1. you can use an HTTP client to follow the redirect and fetch the final URL. Here’s an example using http package:

    import 'package:http/http.dart' as http;
    
    Future<String> getFinalImageUrl(String initialUrl) async {
      var response = await http.get(Uri.parse(initialUrl));
      if (response.statusCode == 302) {
        return response.headers['location'];
      }
      return initialUrl;
    }
    

    I hope this may help you.

    Login or Signup to reply.
  2. The best way to approach this issue is to use a caching solution, for example, flutter_cache_manager if you want to manage the image/URL caching logic yourself or cached_network_image for a composite solution for image handling.

    If all you want to do is cache the images so that they only get loaded once for the app session, or possibly longer, depending on the cache and image size, go for the cached_network_image library. On render of the image widget, an HTTP request is made to download the image and put it in the app’s temporary cache directory for later use. Images loaded in such a way will be reused on subsequent rerenders via the CachedNetworkImageProvider provider. The cached_network_image library uses flutter_cache_manager under the hood to handle insertion of new entries, removal of stale entries, and checks on whether to re-request the image instead of serving it from the cache.

    Here is a minimal demo for you to play around with:

    import 'package:cached_network_image/cached_network_image.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(const MaterialApp(home: MyPage()));
    
    class MyPage extends StatelessWidget {
      const MyPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                CachedNetworkImage(
                  imageUrl: 'https://via.assets.so/img.jpg?w=400&h=400',
                  placeholder: (_, __) => const Center(
                    child: CupertinoActivityIndicator(),
                  ),
                  errorWidget: (_, __, ___) => const Center(
                    child: Icon(Icons.error),
                  ),
                ),
                const SizedBox(height: 24),
                const Text('cached_network_image demo'),
              ],
            ),
          ),
        );
      }
    }
    

    I recommend you play with the demo and request images with different dimensions (width and height) from the API to see how the caching works. Subsequent renders of previously cached images served over the same endpoints will not produce additional HTTP requests, as seen in the DevTools Network section. Also, try closing and reopening (for Android emulators only) or hot restarting (for iOS simulators) the app to see that caching works between app sessions, even if it was terminated.

    DevTools Network section screenshot.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search