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
Implement Caching #48
Comments
Hi there, |
So, since yesterday I've been trying to figure out what I need to do so I don't have to redo everything by looking at the examples and reading your documentation, I'll show you my code, maybe you have some idea of what you need. this is part of the map: ` var _needLoadingError = true;
` This is what I'm trying to cache: `import 'package:cached_network_image/cached_network_image.dart'; class CachedTileProvider extends TileProvider { typedef ErrorResponseHandler = Future<http.Response> Function(Object error, class MyTileProvider extends TileProvider { final VoidCallback onError; @OverRide |
All I want is to make it store the tiles that have already been loaded so that it doesn't get lost, maybe for a day or two it's great, then it can be discarded, the problem is that I'm getting to flutter now, so... |
Ok, so all you need to change is the tile provider to |
You won't be able to transfer existing cached tiles - without manual migration code which is beyond the scope of this library - if that's what you're asking. |
I think I expressed myself poorly! What I need is to store the cache and be able to use it when I'm not on the network, I believe this is the function of the cache, right? And also increase its duration, for example, extend its lifespan by 2 days, you know? |
Yes this is possible. |
You can also set the valid cache duration, which defaults to 16 days per tile. |
Did you mention up there that I'm going to need something like this?
|
No, I think you've misunderstood. For now, you can ignore any tileProvider: StorageCachingTileProvider(parentDirectory: cacheDir, storeName: 'Name',), |
So, trying to do this, it doesn't even start... I even tried to copy part of your code to see if it would work, but it didn't... main.dart import 'package:flutter/material.dart';
import 'package:feature_discovery/feature_discovery.dart';
import 'package:localiza_favoritos/componentes/general_provider.dart';
import 'package:provider/provider.dart';
import 'package:localiza_favoritos/componentes/mapa.dart';
import 'package:localiza_favoritos/componentes/nethort_help.dart';
import 'package:localiza_favoritos/componentes/rota.dart';
import 'package:localiza_favoritos/componentes/tema.dart';
import 'package:localiza_favoritos/screens/cadastro/editar_favoritos.dart';
import 'package:localiza_favoritos/screens/cadastro/formulario_categoria.dart';
import 'package:localiza_favoritos/screens/cadastro/formulario_favoritos.dart';
import 'package:localiza_favoritos/screens/dashboard/chama_paginas_pesquisa.dart';
import 'screens/dashboard/inicio.dart';
void main() {
runApp(CLHApp());
}
// ignore: use_key_in_widget_constructors
class CLHApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FeatureDiscovery(
child: MultiProvider(
providers: [
ChangeNotifierProvider<GeneralProvider>(
create: (context) => GeneralProvider(),
),
],
child: MaterialApp(
theme: localizaTema,
debugShowCheckedModeBanner: false,
//home: FormularioCategoria(),
// home: FormularioCadastro(0.0,0.0),
home: dashboard(0),
routes: {
'/retornoEditaFavorios': (BuildContext context) => dashboard(1),
},
),
),
);
}
} Example code // ignore_for_file: prefer_void_to_null
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
import 'package:shared_preferences/shared_preferences.dart';
class GeneralProvider extends ChangeNotifier {
//! CACHING !//
bool _cachingEnabled = false;
bool get cachingEnabled => _cachingEnabled;
set cachingEnabled(bool newVal) {
_cachingEnabled = newVal;
notifyListeners();
}
String _storeName = 'Default Store';
String get storeName => _storeName;
set storeNameQuiet(String newVal) => _storeName = newVal;
set storeName(String newVal) {
_storeName = newVal;
notifyListeners();
}
Directory? parentDirectory; // Should only be set once
SharedPreferences? persistent; // Should only be set once
//! MISC !//
final StreamController<Null> _resetController = StreamController.broadcast();
StreamController<Null> get resetController => _resetController;
void resetMap() {
_resetController.add(null);
}
String? _storeModalCompletedString;
String? get storeModalCompletedString => _storeModalCompletedString;
set storeModalCompletedString(String? newString) {
_storeModalCompletedString = newString;
notifyListeners();
if (newString != null) {
Future.delayed(const Duration(seconds: 3), () {
_storeModalCompletedString = null;
notifyListeners();
});
}
}
} My map_page import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:localiza_favoritos/componentes/Calculo_de_rota.dart';
import 'package:localiza_favoritos/componentes/cacche_disco.dart';
import 'package:localiza_favoritos/database/DAO/categoria_dao.dart';
import 'package:localiza_favoritos/models/pesquisa_categoria.dart';
import 'package:sliding_up_panel/sliding_up_panel.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
import 'package:flutter_map/plugin_api.dart';
import 'package:latlong2/latlong.dart';
import 'package:routing_client_dart/routing_client_dart.dart';
import 'package:flutter/services.dart';
import 'package:location/location.dart';
import 'package:localiza_favoritos/componentes/search.dart';
import 'package:localiza_favoritos/componentes/nethort_help.dart';
import 'package:localiza_favoritos/componentes/rota.dart';
import 'package:localiza_favoritos/database/DAO/favoritos_dao.dart';
import 'package:localiza_favoritos/models/pesquisa_cliente.dart';
import 'package:localiza_favoritos/screens/cadastro/formulario_favoritos.dart';
class mapa extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MapaState();
}
}
class MapaState extends State<mapa> {
/********************variveis********************/
double long = 106.816666;
double lat = -6.200000;
double zoom = 15.0;
double rotation = 0.0;
late double zoomAtual = 5.0;
LatLng currentCenter = LatLng(51.5, -0.09);
LatLng point = LatLng(-6.200000, 106.816666);
final FitBoundsOptions options =
const FitBoundsOptions(padding: EdgeInsets.all(12.0));
late String pesquisa = '';
List<Marker> markers = [];
List<Marker> markerDb = [];
List<Marker> markersTracker = [];
List<redistro_favoritos> banco = [];
List<registro_categoria> bancoCategoria = [];
String? _error;
/**************************************************/
/*****************Notifier*************************/
ValueNotifier<bool> rastreio = ValueNotifier(false);
/**************************************************/
/*****************Controllers**********************/
MapController mapController = MapController();
late MapState map;
late bool _serviceEnabled;
late Location location = Location();
LocationData? _locationData;
StreamSubscription<LocationData>? _locationSubscription;
/**************************************************/
@override
void initState() {
super.initState();
getCurrentLocation();
addMarkerDb();
}
late int quantidade = 0;
getCurrentLocation() async {
Location getLocation = new Location();
bool _serviceEnabled;
PermissionStatus _permissionGranted;
LocationData? _locationData;
_serviceEnabled = await getLocation.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await getLocation.requestService();
if (!_serviceEnabled) {
return;
}
}
_permissionGranted = await getLocation.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await getLocation.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
_locationData = await getLocation.getLocation();
setState(() {
print(LatLng(parseToDouble(_locationData?.latitude),
parseToDouble(_locationData?.longitude)));
currentCenter = LatLng(parseToDouble(_locationData?.latitude),
parseToDouble(_locationData?.longitude));
mapController.move(
LatLng(parseToDouble(_locationData?.latitude),
parseToDouble(_locationData?.longitude)),
13.0);
});
}
@override
Widget build(BuildContext context) {
final TextEditingController controladorCampoPesquisa =
TextEditingController();
var _needLoadingError = true;
return Scaffold(
appBar: AppBar(
title: Text('Mapa'),
),
body: Center(
child: Stack(children: [
FlutterMap(
mapController: mapController,
options: MapOptions(
maxZoom: 18,
minZoom: 4,
center: currentCenter,
zoom: zoomAtual,
onTap: (latlng) {
removeMarker();
setState(() {
addMarker(latlng);
});
},
plugins: [],
slideOnBoundaries: true,
screenSize: MediaQuery.of(context).size,
),
layers: [
TileLayerOptions(
//tileProvider: MyTileProvider(onError: _onTileError),
tileProvider: StorageCachingTileProvider(cachedValidDuration: Duration(days: 15), cacheName: 'Mapa_cache'),
urlTemplate:
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: ['a', 'b', 'c'],
//tileProvider: NonCachingNetworkTileProvider(),
//tileProvider: const CachedTileProvider(),
updateInterval: 1,
errorTileCallback: (Tile tile, error) {
if (_needLoadingError) {
WidgetsBinding.instance!.addPostFrameCallback((_) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: Duration(seconds: 1),
content: Text(
error.toString(),
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.deepOrange,
));
});
_needLoadingError = false;
}
throw Exception('Unknown error, description: $error');
}),
MarkerLayerOptions(markers: [
for (int i = 0; i < markers.length; i++) markers[i]
]),
MarkerLayerOptions(markers: [
for (int i = 0; i < markerDb.length; i++) markerDb[i]
]),
MarkerLayerOptions(markers: [
for (int i = 0; i < markersTracker.length; i++)
markersTracker[i],
]),
]),
[...] Fatal error
|
I can't see any major issues in your map page though, so it should work after you follow the above steps. |
Hello, so... I followed your tips there, and really, those bugs were gone... However, the Storege is asking me for a directory... How can I pass a directory to it without me creating one like I was trying to do in the previous code? `TileLayerOptions(
|
I tried to create a directory to be able to pass a cache address to it and it returned this error **What did I do pubspec.yaml** `name: localiza_favoritos publish_to: 'none' # Remove this line if you wish to publish to pub.dev https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html environment: dependencies: dev_dependencies: flutter_lints: ^1.0.0 flutter: assets: mapa.dart
error `Launching lib\main.dart on LM K200 in debug mode... FAILURE: Build failed with an exception.
BUILD FAILED in 2m 53s |
This is solved: |
I solved this error by doing this https://github.com/transistorsoft/flutter_background_fetch/blob/master/help/INSTALL-ANDROID.md after following the above link, do: delete the 'multi-v2' folder that is in the directory: run flutter clean |
Now I'm back to the previous point... Create a directory for the cache that the function is asking for... But how? |
Use |
Then,
I'm doing like this
|
Are you sure that the |
So, for me to use a FutureBuilder I would have to change the whole structure to be able to return the directory, right? I'm trying to find a way to use the cache without having to change the entire structure... Because the app is already working, and for me to change everything it would take two or three weeks |
And I have 3 days to deliver this project, I can't delay any longer |
Unless, what you're trying to tell me is that I can wrap |
Then, the code is this... I still believe I need more than one FutureBuilder in there... I'm having the following error now: `import 'dart:io'; pegaDiretorio() async {
}`
|
The easiest way to do it in your case would probably be to await the normal cache in the |
You shouldn't need to use path_provider. |
I'm trying to implement caching to work with Flutter and Flutter_Map. I found an api to work with that makes the process a little easier. However, when I disable the internet, (I put it in airplane mode) it gives me an error. I'm not finding the source of this error. Can someone help me? Code block I'm using to work with cache:
Code block I'm using to map and pull cache:
This is the error:
This is the Output :
I'm assuming the error being returned is not about where I'm loading the cache... I tried loading the cache in main and it didn't work... I couldn't... It is loading the cache as is, this is shown in the output below Restarted application in 9.358ms. |
Ok, so it appears it is correctly setup now, as I can see from the paths.
are created by this line in this file (link to github.dev), and indicate that:
Therefore, it would appear that the tile is not already in the cache, and there is no Internet, and therefore this library cannot do anything else but throw. Many thanks. |
So what you're telling me is it's a bug in your library? |
I tried doing checks to make sure the tile already existed in cache, but it didn't work... It seems it doesn't recognize it as a provider and won't let me check it... |
What do you mean by 'it doesn't recognize it as a provider and won't let me check it...'? To check map statistics, you should use |
There is very little chance of a bug on my side:
|
Have you resolved your issue? Happy to help more if required! |
Ah Jaffa Ketchup, I'm very frustrated. I couldn't... I've been trying for days and I haven't made any progress on this. It always returns the same error |
Sorry I haven't been more help; is there anything that I can do better, or give you more help? |
My page where I call the map and cache My pubspec.yaml Meu projeto inteiro Error when activating airplane mode (multiple times):
|
Thank you so much for making yourself available to help me. I really don't know what else to do... |
As in some posts ago you commented about loading the cache in main.dart, I tried to do that, but it didn't work... |
Hi @AlysonTrizotto, |
Hi @JaffaKetchup, well if this is the expected behavior my problem is in handling this output!! Thank you so much for sharing your knowledge and taking the time to help me!!! |
No problem, hope you can find a way to handle it :) |
Yes, I was looking for a solution to a non-existent problem... Now the situation has cleared up. |
I had the same error, I made some changes in plugin and it fixed the problem. Especially not closing the httpclient on dispose. here is my implementation. https://github.com/sikandernoori/flutter_map_tile_caching-6.1.0 |
Hello, I have a project in a very advanced stage already, and I wanted to implement caching in it, so I can use your api, will I need to redo all of it? Or do you have one that you don't need? I saw that your api is for Flutter_map, and I'm using flutter_map. Do I need to redo it all to be able to use your api?
The text was updated successfully, but these errors were encountered: