Skip to content

Commit

Permalink
Merge pull request beerstorm-net#26 from pawlowskim/master
Browse files Browse the repository at this point in the history
Possibility to get direct rxdart stream to avoid memory leaks
  • Loading branch information
zeusbaba authored Mar 10, 2023
2 parents d604857 + 9d52535 commit d95210b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2.3.15
* provide option to listen on source location stream which doesn't cause memory leaks

## 2.3.14
* upgrade dependencies
* fix for query results duplicate after 1250km as described in [this issue](https://github.com/beerstorm-net/GeoFlutterFire2/issues/13)
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ Calling `geoFirePoint.data` returns an object that contains a [geohash string](h
![](https://firebasestorage.googleapis.com/v0/b/geo-test-c92e4.appspot.com/o/point1.png?alt=media&token=0c833700-3dbd-476a-99a9-41c1143dbe97)
## Query Geo data
> **Warning**
> Querying locations creates 9 separated stream listeners on firestore. One for central geo hash and 8 surrounding it.
> `within` function creates a convenient broadcast stream, if you need more than one subscriber for the locations. But it also causes
> memory leak, because underlying stream listeners are not cancelled when you cancel StreamSubscription from `within` method.
>
> It's much safer to use withinAsSingleStreamSubscription which you can cancel, and it will also cancel 9 underlying streams as well.
To query a collection of documents with 50kms from a point
Expand Down Expand Up @@ -220,4 +226,4 @@ radius.add(25);
### Acknowledgements
**NB! `GeoFlutterFire2` is a revisited and updated version of [GeoFlutterFire](https://github.com/DarshanGowda0/GeoFlutterFire)**
The work originates from [GeoFlutterFire](https://github.com/DarshanGowda0/GeoFlutterFire) by Darshan Narayanaswamy
The work originates from [GeoFlutterFire](https://github.com/DarshanGowda0/GeoFlutterFire) by Darshan Narayanaswamy
58 changes: 54 additions & 4 deletions lib/src/collection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,12 @@ class GeoFireCollectionRef {
}
}

/// query firestore documents based on geographic [radius] from geoFirePoint [center]
/// [field] specifies the name of the key in the document
Stream<List<DocumentSnapshot>> within({
/// Create combined stream listeners for each geo hash around (including) central point.
/// It creates 9 listeners and the hood.
///
/// Returns [StreamController.stream] instance from rxdart, which is combined stream,
/// for all 9 listeners.
Stream<List<DocumentSnapshot>> _buildQueryStream({
required GeoFirePoint center,
required double radius,
required String field,
Expand Down Expand Up @@ -140,7 +143,54 @@ class GeoFireCollectionRef {
});
return filteredList.map((element) => element.documentSnapshot).toList();
});
return filtered.asBroadcastStream();
return filtered;
}

/// Query firestore documents based on geographic [radius] from geoFirePoint [center]
/// [field] specifies the name of the key in the document
/// returns merged stream as broadcast stream.
///
/// Returns original stream from the underlying rxdart implementation, which
/// could be safely cancelled without memory leaks. It's single stream subscription,
/// so only single listener could be created at a time.
///
/// This works the best if you have central point of listening for locations,
/// not per widget.
Stream<List<DocumentSnapshot>> withinAsSingleStreamSubscription({
required GeoFirePoint center,
required double radius,
required String field,
bool strictMode = false,
}) {
return _buildQueryStream(
center: center,
radius: radius,
field: field,
strictMode: strictMode,
);
}

/// Query firestore documents based on geographic [radius] from geoFirePoint [center]
/// [field] specifies the name of the key in the document
/// returns merged stream as broadcast stream.
///
/// !WARNING! This causes memory leaks because under the hood rxdart StreamController
/// never causes it's subscriptions to be cancelled. So, even you cancel stream
/// subscription created from this method, under the hood listeners are still working.
///
/// More at: https://github.com/dart-lang/sdk/issues/26686#issuecomment-225346901
Stream<List<DocumentSnapshot>> within({
required GeoFirePoint center,
required double radius,
required String field,
bool strictMode = false,
}) {
return _buildQueryStream(
center: center,
radius: radius,
field: field,
strictMode: strictMode,
).asBroadcastStream();
}

Stream<List<DistanceDocSnapshot>> mergeObservable(
Expand Down

0 comments on commit d95210b

Please sign in to comment.