In my application I have several streams.
This is from example app from appsflyer. I use it for deep linking my application.
https://pub.dev/packages/appsflyer_sdk
in first page we have ;
return Scaffold(
appBar: AppBar(
title: Column(
children: <Widget>[
Text('AppsFlyer SDK example app'),
FutureBuilder<String>(
future: _appsflyerSdk.getSDKVersion(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Text(snapshot.hasData ? snapshot.data : "");
})
],
),
),
body: FutureBuilder<dynamic>(
future: _appsflyerSdk.initSdk(
registerConversionDataCallback: true,
registerOnAppOpenAttributionCallback: true),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
if (snapshot.hasData) {
return HomeContainer(
onData:
_appsflyerSdk.conversionDataStream?.asBroadcastStream(),
onAttribution: _appsflyerSdk.appOpenAttributionStream
?.asBroadcastStream(),
trackEvent: logEvent,
);
} else {
return Center(child: Text("Error initializing sdk"));
}
}
}),
);
in HomeContainer
Stream<Map> onData;
Stream<Map> onAttribution;
Future<bool> Function(String, Map) trackEvent;
HomeContainer({this.onData, this.onAttribution, this.trackEvent});
inside build;
Column(
children: <Widget>[
StreamBuilder<dynamic>(
stream: widget.onData,
builder:
(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
return TextBorder(
controller: TextEditingController(
text: snapshot.hasData
? Utils.formatJson(snapshot.data)
: "No conversion data"),
labelText: "Conversion Data:",
);
}),
Padding(
padding: EdgeInsets.only(top: 12.0),
),
StreamBuilder<dynamic>(
stream: widget.onAttribution,
builder:
(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
return TextBorder(
controller: TextEditingController(
text: snapshot.hasData
? _processData(snapshot.data)
: "No attribution data"),
labelText: "Attribution Data:",
);
}),
],
),
What I have done is to put a button to reload the screens, using a notifyListeners.
When I do that, I get following error;
Bad state: Stream has already been listened to.
I assume, the problem may be due to these streams are still open when I reload the page.
But I don't know how to close them.
Can anyone provide some assistance on this?
StreamBuilder<dynamic>(
stream: widget.onData?.asBroadcastStream(),
You're calling asBroadcastStream()
multiple times (every time the build method is called) on widget.onData
. You should be able to just use:
StreamBuilder<dynamic>(
stream: widget.onData,
And if widget.onData
is listened to elsewhere, make sure widget.onData
itself is a broadcast stream.