mirror of https://github.com/AMT-Cheif/drift.git
Make query streams emit their last item for new listeners
This commit is contained in:
parent
3024157ec9
commit
59235783c3
|
@ -1,3 +1,6 @@
|
||||||
|
## 1.5.1
|
||||||
|
- Fixed an issue where streams would behave inconsistently when transformed.
|
||||||
|
|
||||||
## 1.5.0
|
## 1.5.0
|
||||||
This version introduces some new concepts and features, which are explained in more detail below.
|
This version introduces some new concepts and features, which are explained in more detail below.
|
||||||
Here is a quick overview of the new features:
|
Here is a quick overview of the new features:
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:async';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
|
import 'package:moor/src/utils/start_with_value_transformer.dart';
|
||||||
|
|
||||||
const _listEquality = ListEquality<dynamic>();
|
const _listEquality = ListEquality<dynamic>();
|
||||||
|
|
||||||
|
@ -120,17 +121,24 @@ class QueryStream<T> {
|
||||||
// caching the stream so that the stream getter always returns the same stream
|
// caching the stream so that the stream getter always returns the same stream
|
||||||
Stream<T> _stream;
|
Stream<T> _stream;
|
||||||
|
|
||||||
|
T _lastData;
|
||||||
|
|
||||||
Stream<T> get stream {
|
Stream<T> get stream {
|
||||||
_controller ??= StreamController.broadcast(
|
_controller ??= StreamController.broadcast(
|
||||||
onListen: _onListen,
|
onListen: _onListen,
|
||||||
onCancel: _onCancel,
|
onCancel: _onCancel,
|
||||||
);
|
);
|
||||||
|
|
||||||
return _stream ??= _controller.stream;
|
return _stream ??=
|
||||||
|
_controller.stream.transform(StartWithValueTransformer(_cachedData));
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryStream(this._fetcher, this._store);
|
QueryStream(this._fetcher, this._store);
|
||||||
|
|
||||||
|
/// Called when we have a new listener, makes the stream query behave similar
|
||||||
|
/// to an `BehaviorSubject` from rxdart.
|
||||||
|
T _cachedData() => _lastData;
|
||||||
|
|
||||||
void _onListen() {
|
void _onListen() {
|
||||||
// first listener added, fetch query
|
// first listener added, fetch query
|
||||||
fetchAndEmitData();
|
fetchAndEmitData();
|
||||||
|
@ -151,6 +159,7 @@ class QueryStream<T> {
|
||||||
if (!_controller.hasListener) return;
|
if (!_controller.hasListener) return;
|
||||||
|
|
||||||
final data = await _fetcher.fetchData();
|
final data = await _fetcher.fetchData();
|
||||||
|
_lastData = data;
|
||||||
|
|
||||||
if (!_controller.isClosed) {
|
if (!_controller.isClosed) {
|
||||||
_controller.add(data);
|
_controller.add(data);
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
/// Signature of a function that returns the latest current value of a
|
||||||
|
/// [StartWithValueTransformer].
|
||||||
|
typedef LatestValue<T> = T Function();
|
||||||
|
|
||||||
|
/// Lightweight implementation that turns a [StreamController] into a behavior
|
||||||
|
/// subject (we try to avoid depending on rxdart because of its size).
|
||||||
|
class StartWithValueTransformer<T> extends StreamTransformerBase<T, T> {
|
||||||
|
final LatestValue<T> _value;
|
||||||
|
|
||||||
|
StartWithValueTransformer(this._value);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<T> bind(Stream<T> stream) {
|
||||||
|
// we're setting sync to true because we're proxying events
|
||||||
|
final controller = StreamController<T>.broadcast(sync: true);
|
||||||
|
|
||||||
|
// ignore: cancel_subscriptions
|
||||||
|
StreamSubscription subscription;
|
||||||
|
|
||||||
|
controller
|
||||||
|
..onListen = () {
|
||||||
|
final data = _value();
|
||||||
|
if (data != null) {
|
||||||
|
controller.add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscription = stream.listen(
|
||||||
|
controller.add,
|
||||||
|
onError: controller.addError,
|
||||||
|
onDone: controller.close,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
..onCancel = () {
|
||||||
|
// not using a tear-off here because subscription.cancel is null before
|
||||||
|
// onListen has been called
|
||||||
|
subscription?.cancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return controller.stream;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue