-
-
Notifications
You must be signed in to change notification settings - Fork 868
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
Handle exception on move without internet connection #593
Comments
The only way I can think of handling this is using a custom A plugin, paired with a tile provider might be a better fit, since it has access to the map state, thus will be able to invoke a reload on the visible tiles. |
User won't see console and as far as I know Leaflet will flood console too if there is no internet connection avaible (I tested it on browser). Anyway Flutter caches Network Images even if they loaded with error (forinstance no internet connection) so the Tiles gets stuck, take a look on #577 PR, I am goind to add connection detect strategy soon. |
@beerline - this sounds like business logic, that’s not related to the plugin. I would say that this plugin is not supposed to handle the user facing connectivity notifications. It can handle it internally for a better user experience, but it is the developer’s job to handle connectivity state changes and notify the user accordingly in a way that makes sense for the final app. |
@avioli totally agree with you, that this is business logic try{
map.move(centerZoom.center, zoom);
} catch (e) {
// handle error here
} But since it useing strams under the hood I also tried to subscribe to subscribe to this stream map.onMoved(
(_){},
onError: (error) {
// handle error here
}
);
map.move(centerZoom.center, zoom); But In theory, i can check internet connection before each call may be you can suggest better solution how i can handle this exception, i will be grateful to you |
I think the easiest way to do this if you provide some callback method to
Note if you have multiple Tile Layers then you should pass your callback to every layer's |
If you are using the default tileProvider: class MyTileProvider extends TileProvider {
MyTileProvider({ this.onError });
final VoidCallback onError;
@override
ImageProvider getImage(Coords<num> coords, TileLayerOptions options) {
final url = getTileUrl(coords, options);
return CachedNetworkImageProvider(url, errorListener: onError);
}
} Then in your Widget: Widget build(BuildContext context) {
return FlutterMap(
...
layers: [
TileLayerOptions(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
tileProvider: MyTileProvider(onError: _onTileError),
),
],
);
}
void _onTileError() {
print("uh-oh - a tile couldn't load");
} Unfortunately, given that |
Then... if you want to go crazy you can try to get a grip of the cache manager that // other imports
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_cache_manager/src/web_helper.dart'; // ignore: implementation_imports
import 'package:flutter_map/flutter_map.dart';
import 'package:http/http.dart' as http;
typedef ErrorResponseHandler = Future<http.Response> Function(Object error,
[StackTrace stack]);
class MyTileProvider extends TileProvider {
MyTileProvider({this.errorHandler});
final ErrorResponseHandler errorHandler;
@override
ImageProvider getImage(Coords<num> coords, TileLayerOptions options) {
final url = getTileUrl(coords, options);
final cacheManager = MyCacheManager.instance..errorHandler = errorHandler;
return CachedNetworkImageProvider(
url,
cacheManager: cacheManager,
);
}
}
class MyCacheManager extends BaseCacheManager {
static MyCacheManager _instance;
static MyCacheManager get instance => _instance ??= MyCacheManager._();
MyCacheManager._() : super(DefaultCacheManager.key) {
webHelper = WebHelper(store, _fetch);
}
ErrorResponseHandler errorHandler;
@override
Future<String> getFilePath() => DefaultCacheManager().getFilePath();
Future<FileFetcherResponse> _fetch(String url,
{Map<String, String> headers}) async {
try {
final response = await http.get(url, headers: headers);
return new HttpFileFetcherResponse(response);
} catch (e, stack) {
if (errorHandler != null) {
final response = await errorHandler(e, stack);
return new HttpFileFetcherResponse(response);
}
rethrow;
}
}
} Then use it like so: Widget build(BuildContext context) {
return FlutterMap(
...
layers: [
TileLayerOptions(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
tileProvider: MyTileProvider(errorHandler: _onTileError), // <-- changed
),
],
);
}
// This now gets an error object and a stack trace, but only for internet downloads,
// not for disk failures
Future<http.Response> _onTileError(Object err, [StackTrace stack]) {
print("uh-oh - a tile couldn't load");
print("error: $err");
print(stack);
return Future.error(err, stack);
} The errors you'll get look like this:
|
@avioli thank you for your solution! |
Implementrd this solution #593 (comment) PR: #600 |
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days. |
This issue was closed because it has been stalled for 5 days with no activity. |
Still not solved. Shouldn't it be added as an issue? |
Didn't the PR #600 fix it ? |
Hi flutter_map team!
How I can handling exception while user move or zoom map but internet connect is lost?
Steps to do:
Open app with interne
Code the same as in this example
console errors
Thank you for your help!
The text was updated successfully, but these errors were encountered: