Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Offline Mapping #798

Closed
wants to merge 11 commits into from
Closed

Better Offline Mapping #798

wants to merge 11 commits into from

Conversation

JaffaKetchup
Copy link
Member

@JaffaKetchup JaffaKetchup commented Jan 6, 2021

As a follow up to issue #795, I have created this pull request. Please note the differentiation between existing caching solutions and this new solution: caches can be cleared without warning by the system, app storage can't.

I have added a new tile provider to be used as below:

Use PersistentAdvancedCacheTileProvider() as the TileLayerOptions > tileProvider option, and set TileLayerOptions > saveDir to a variable containing (await) getApplicationDocumentsDirectory() from library path_provider.

As the user scrolls around the map, tiles will be saved to [saveDir]/tiles. Then, when requested again, tiles will be taken from that directory if available, else a network tile request will be made. Thus, this is a file first solution.

This configuration should be used where offline functionality is required because cached tiles from other tile providers can be cleaned by the system without user notification at any point. With this setup, only the user (through App Settings > Storage > Clear Storage) or the app itself can clear the tiles. It is up to the app developer (you) to manage these tiles...

If your user wants to get the latest tiles from the server for tiles already loaded, you must clear the tiles folder. If the user wishes to remove tiles altogether, you must provide that functionality. This library will not handle that for you.

A recommended (however untested) integration is to use another tile provider (such as the default) whilst not in 'Offline Mode' so that the newest tiles are always loaded, then switch to this provider once the user enters 'Download & Offline Mode'. Then, when the user switches back out, clear the tiles folder.

This pull request adds one dependency. This PR has only been tested on an Android Pixel 3a emulator.

@JaffaKetchup
Copy link
Member Author

JaffaKetchup commented Jan 6, 2021

I hadn't seen #564 before creating this pull request. Whilst that PR does look and probably function better (I'm still new to this), there is one major advantage of this PR: size. This PR adds under 30 lines of code in total. If maintainer would like this closed, I am happy to 👍.
I'd also be happy with adding the tiles clearing feature if neccessary.

@johnpryan
Copy link
Collaborator

Any custom tile providers aren't likely to be added at this point, since you can build your own package that provides them. This keeps the core package small. Feel free to suggest any packages you would like mentioned in the README.

@stevenv-synap
Copy link

I see that some people have struggled with caching tiles/improving tile load timings on the web platform. My solution was to introduce a custom TileProvider (Allows configuration of the HTTP requests, if required), and then usage of the extended_image package allowed for caching of images at the browser level (same sort of behaviour you would get with Cache-Control response headers on any website).

Image Package:
https://pub.dev/packages/extended_image
The ExtendedNetworkImageProvider class provides the caching capabilities.

class DioTileProvider extends TileProvider {
  final Dio dio;

  DioTileProvider({
    Map<String, String> headers = const {},
    Dio? httpClient,
  })  : dio = httpClient ?? Dio(),
        super(
          headers: {
            ...headers,
            'User-Agent': headers['User-Agent'] == null
                ? 'flutter_map_tile_caching for flutter_map (unknown)'
                : 'flutter_map_tile_caching for ${headers['User-Agent']}',
          },
        );

  @override
  ImageProvider<Object> getImage(
      TileCoordinates coordinates, TileLayer options) {
    var tileUrl = getTileUrl(coordinates, options);
    return ExtendedNetworkImageProvider(tileUrl,
        cache: true, cacheMaxAge: const Duration(days: 15));
  }

  @override
  void dispose() {
    dio.close();
    super.dispose();
  }
}

Hope this helps. Cheers

@JaffaKetchup
Copy link
Member Author

JaffaKetchup commented Sep 13, 2023

Hey @stevenv-synap,

Session caching will come back in v6, so hopefully this shouldn't be necessary. There are also some other improvements to load time!

There's also another caching plugin available that's a little simpler than FMTC, but less flexible. More info available on the V6 docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants