Created
August 11, 2020 15:49
-
-
Save MariaMelnik/3f2ca839b39191e0a61e0bbf064feed4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:flutter/material.dart'; | |
abstract class MyStreamBuilderBase<T, S> extends StatefulWidget { | |
/// Creates a [MyStreamBuilderBase] connected to the specified [stream]. | |
const MyStreamBuilderBase({ Key key, this.stream }) : super(key: key); | |
/// The asynchronous computation to which this builder is currently connected, | |
/// possibly null. When changed, the current summary is updated using | |
/// [afterDisconnected], if the previous stream was not null, followed by | |
/// [afterConnected], if the new stream is not null. | |
final Stream<T> stream; | |
/// Returns the initial summary of stream interaction, typically representing | |
/// the fact that no interaction has happened at all. | |
/// | |
/// Sub-classes must override this method to provide the initial value for | |
/// the fold computation. | |
S initial(); | |
/// Returns an updated version of the [current] summary reflecting that we | |
/// are now connected to a stream. | |
/// | |
/// The default implementation returns [current] as is. | |
S afterConnected(S current) => current; | |
/// Returns an updated version of the [current] summary following a data event. | |
/// | |
/// Sub-classes must override this method to specify how the current summary | |
/// is combined with the new data item in the fold computation. | |
S afterData(S current, T data); | |
/// Returns an updated version of the [current] summary following an error. | |
/// | |
/// The default implementation returns [current] as is. | |
S afterError(S current, Object error) => current; | |
/// Returns an updated version of the [current] summary following stream | |
/// termination. | |
/// | |
/// The default implementation returns [current] as is. | |
S afterDone(S current) => current; | |
/// Returns an updated version of the [current] summary reflecting that we | |
/// are no longer connected to a stream. | |
/// | |
/// The default implementation returns [current] as is. | |
S afterDisconnected(S current) => current; | |
/// Returns a Widget based on the [currentSummary]. | |
Widget build(BuildContext context, S currentSummary); | |
@override | |
State<MyStreamBuilderBase<T, S>> createState() => _MyStreamBuilderBaseState<T, S>(); | |
} | |
/// State for [MyStreamBuilderBase]. | |
class _MyStreamBuilderBaseState<T, S> extends State<MyStreamBuilderBase<T, S>> { | |
StreamSubscription<T> _subscription; | |
S _summary; | |
@override | |
void initState() { | |
super.initState(); | |
_summary = widget.initial(); | |
_subscribe(); | |
} | |
@override | |
void didUpdateWidget(MyStreamBuilderBase<T, S> oldWidget) { | |
super.didUpdateWidget(oldWidget); | |
if (oldWidget.stream != widget.stream || oldWidget.initial() != widget.initial()) { | |
if (_subscription != null) { | |
_unsubscribe(); | |
_summary = widget.afterDisconnected(_summary); | |
} | |
_subscribe(); | |
} | |
} | |
@override | |
Widget build(BuildContext context) => widget.build(context, _summary); | |
@override | |
void dispose() { | |
_unsubscribe(); | |
super.dispose(); | |
} | |
void _subscribe() { | |
if (widget.stream != null) { | |
_subscription = widget.stream.listen((T data) { | |
setState(() { | |
_summary = widget.afterData(_summary, data); | |
}); | |
}, onError: (Object error) { | |
setState(() { | |
_summary = widget.afterError(_summary, error); | |
}); | |
}, onDone: () { | |
setState(() { | |
_summary = widget.afterDone(_summary); | |
}); | |
}); | |
_summary = widget.afterConnected(_summary); | |
} | |
} | |
void _unsubscribe() { | |
if (_subscription != null) { | |
_subscription.cancel(); | |
_subscription = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment