geo_lat_lon 0.0.5
geo_lat_lon: ^0.0.5 copied to clipboard
geo_lat_lon enables your flutter app to store and query cloud firestore documents based on their geographic location.
π¦ geo_lat_lon #
geo_lat_lon is a modern Dart/Flutter package for performing geospatial queries on Cloud Firestore using geohashes. It is a fork of the geoflutterfire_plus package, with updated code and design improvements to support the latest versions of Flutter and Firestore SDKs.
π Features #
- Add, update, and delete documents with location data
- Perform radius-based geo queries
- Subscribe to real-time location updates
- Calculate geohash precision automatically
- Client-side filtering for precise results
- Supports Firestore typed converters
π§± Installation #
Add the package to your pubspec.yaml:
dependencies:
geo_lat_lon: <latest_version>
π§± Structure #
β
GeoCollectionReference<T> #
An enhanced wrapper around Firestoreβs CollectionReference<T> that enables querying by geohash and location.
add(T data)set(...)updatePoint(...)delete(...)fetchWithin(...)subscribeWithin(...)
π GeoFirePoint #
Encapsulates a Firestore GeoPoint and provides:
geohashneighborsdistanceBetweenInKm(...)dataβ to be saved into Firestore
π GeoDocumentSnapshot<T> #
A wrapper for Firestore DocumentSnapshot with calculated distance from a center point.
π Real-time Query Example #
final geoRef = GeoCollectionReference<ShopModel>(shopCollection);
geoRef.subscribeWithin(
center: GeoFirePoint(GeoPoint(23.81, 90.41)),
radiusInKm: 5.0,
field: 'location',
geopointFrom: (shop) => shop.location,
).listen((snapshots) {
for (final doc in snapshots) {
print(doc.data());
}
});
π Firestore Document Structure #
{
"location": {
"geopoint": GeoPoint(23.8103, 90.4125),
"geohash": "w21zv0h9"
},
"name": "Shop 01",
"isVisible": true
}
π§βπ» Example Usage #
Define Your Model #
class Location {
final Geo geo;
final String name;
final bool isVisible;
Location({required this.geo, required this.name, required this.isVisible});
factory Location.fromJson(Map<String, dynamic> json) => Location(
geo: Geo.fromJson(json['geo']),
name: json['name'],
isVisible: json['isVisible'] ?? false,
);
Map<String, dynamic> toJson() => {
'geo': geo.toJson(),
'name': name,
'isVisible': isVisible,
};
factory Location.fromDocumentSnapshot(DocumentSnapshot doc) =>
Location.fromJson(doc.data() as Map<String, dynamic>);
}
class Geo {
final String geohash;
final GeoPoint geopoint;
Geo({required this.geohash, required this.geopoint});
factory Geo.fromJson(Map<String, dynamic> json) => Geo(
geohash: json['geohash'],
geopoint: json['geopoint'],
);
Map<String, dynamic> toJson() => {
'geohash': geohash,
'geopoint': geopoint,
};
}
Define Converter #
class LocationFireStoreModelConverter extends IFireStoreModelConverter<Location> {
@override
Location fromFireStore(DocumentSnapshot<Map<String, dynamic>> snapshot) {
return Location.fromDocumentSnapshot(snapshot);
}
@override
Map<String, dynamic> toFireStore(Location model) {
return model.toJson();
}
}
Create a Typed Collection Reference #
final locationCollection = typedCollectionReference<Location>(
path: 'locations',
converter: LocationFireStoreModelConverter(),
);
Subscribe to Geo Query #
final geoRef = GeoCollectionReference<Location>(locationCollection);
geoRef.subscribeWithin(
center: GeoFirePoint(GeoPoint(23.81, 90.41)),
radiusInKm: 5.0,
field: 'geo',
geopointFrom: (location) => location.geo.geopoint,
).listen((snapshots) {
for (final doc in snapshots) {
print(doc.data().name);
}
});
π Firestore Document Structure #
{
"geo": {
"geopoint": GeoPoint(23.8103, 90.4125),
"geohash": "w21zv0h9"
}
}
Use the GeoFirePoint class to generate this data consistently.
final point = GeoFirePoint(GeoPoint(23.8103, 90.4125));
final data = point.data; // {'geopoint': ..., 'geohash': ...}
π How It Works #
- π Geohash Encoding: Converts lat/lng to a geohash string.
- πΆ Neighboring Hashes: Queries current and surrounding geohash cells.
- π Range Querying: Performs Firestore queries with
startAt/endAtfor geohash ranges. - π§ Client-side Filtering: Optionally filters results strictly based on radius.
- π Sorting: Results are sorted by proximity.
β οΈ Notes #
- Always use
GeoFirePointwhen saving or updating geo fields. - Use
strictMode: truewhen you want distance-accurate filtering. - This package requires Firestore indexing on the geohash field
- Avoid radius smaller than 0.5 km for edge-case accuracy
- Client-side sorting is preferred over Firestore
orderBy
π Credits #
Forked and evolved from geoflutterfire_plus with support for latest Dart, Flutter, and Firestore SDK.
π References #
π¨βπΌ Contributing #
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Made with β€οΈ by the geo_lat_lon team.