web-dev-qa-db-de.com

Flutter: Schlechter Zustand: Stream wurde bereits angehört

 Die Klasse MyPage erweitert StatelessWidget {
 @override 
 Widget erstellen (BuildContext-Kontext) {
 return DefaultTabController (
 Länge: 2, 
 child: new Scaffold (
 appBar: TabBar (
 tabs: [
 tabs): [
 Tab (child: Text ("MY INFORMATION"), Stil: TextStyle (color : Colors.black54),)), 
 Tab (untergeordnetes Element: Text ("WEB CALENDER"), Stil: TextStyle (Farbe: Colors.black54))), 
], 
), 
 body: PersonalInformationBlocProvider (
 movieBloc: PersonalInformationBloc (), 
 child: TabBarView (
 children: [
 MyInformation (), 
 new SmallCalendarExample (), 
], 
) , 
), 
), 
); 
 } 
 } 

 class MyInformation erweitert StatelessWidget {
 // TODO: implementiere build 
 var deviceSize; 

 //Column1
 Widget profileColumn (Snapshot PersonalInformation) => Container (
 Height: deviceSize.height * 0.24, 
 Child: Spalte (
 MainAxisAlignment: MainAxisAlignment.center, 
 Children: [
 Row (
). Row (
). mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
 children: [
 Container (
 Dekoration: BoxDecoration (
 borderRadius: 
 new BorderRadius.all (new Radius.circular (50.0)), 
 border: new Border.all (
 color: Colors.black, 
 width: 4.0, 
), 
), 
 child: CircleAvatar (
 backgroundImage: NetworkImage (
). "http://www.binaythapa.com.np/img/me.jpg"),
 Vordergrundfarbe: Colors.white, 
 backgroundColor: Colors.white, 
 Radius: 40,0, 
 ), 
 ), 
 ProfileTile (
 Title: snapshot.firstName, 
 Untertitel: "Entwickler", 
), 
 SizedBox (
 Höhe: 10.0, 
), 
 ], 
 ) 
 ], 
 ), 
 ); 
 Widget bodyData (Snapshot PersonalInformation) {
 return SingleChildScrollView (
 child: Column (
 children: [
 profileColumn (Momentaufnahme) 
], 
), 
); 
 } 


 @override 
 Widget erstellen (BuildContext-Kontext) {
 final personalInformationBloc = PersonalInformationBlocProvider.of (Kontext); 

 deviceSize = MediaQuery.of (Kontext) .size; 
 return StreamBuilder (
 stream: personalInformationBloc.results, 
 builder: (Kontext, Momentaufnahme) {
 if (! snapshot.hasData) 
 return Center (
 child: CircularProgressIndicator (), 
); 
 return bodyData (snapshot.data); 
} 
); 
 } 
 } 


Ich verwende Bloc Pattern zum Abrufen von Daten von der Rest-API (nur ganzes Objekt von Json und geparstem Benutzernamen genannt). Die Seite besteht aus zwei Registerkarten MyIformation und SmallCalendar. Wenn die App läuft, werden die Daten korrekt abgerufen und alles ist gut. Wenn ich zu Register zwei gehe und zu Register eins zurückkehre, werden die gesamten Bildschirme in Register eins rot und zeigen den Fehler an: Bad state: Stream has already been listened to.

7
Mercy peka

Das Problem bestand darin, dass die Steuerungen nicht im Block angeordnet waren.

  void dispose() {
    monthChangedController.close();
    dayPressedController.close();
    resultController.close();
  }
0
Mercy peka

Die gebräuchlichste Form von Stream kann jeweils nur einmal gehört werden. Wenn Sie versuchen, mehrere Listener hinzuzufügen, wird dies ausgelöst 

Schlechter Zustand: Stream wurde bereits angehört

Um diesen Fehler zu vermeiden, machen Sie eine broadcast Stream verfügbar. Sie können Ihren Stream mit myStream.asBroadcastStream in eine Sendung konvertieren.

Dies muss in Ihrer Klasse gemacht werden, die Stream verfügbar macht. Nicht als Parameter von StreamBuilder. Da asBroadcastStream intern den ursprünglichen Stream abhört, um den Broadcast-Stream zu generieren, können Sie diese Methode nicht zweimal für denselben Stream aufrufen.

5
Rémi Rousselet

Sie sollten Folgendes verwenden.

StreamController<...> _controller = StreamController<...>.broadcast();
5
amenbo

In meinem Fall wurde dieser Fehler angezeigt, weil dieselbe Codezeile myStream.listen() zweimal im selben Widget im selben Stream aufgerufen wurde. Anscheinend ist das nicht erlaubt!

Was es für mich behoben hat, ist, sowohl einen My Stream Controller als auch einen Broadcast Stream Controller zu erstellen:

var myStreamController = StreamController<bool>.broadcast();

UND

verwende Stream als Broadcast Stream:

myStreamController.stream.asBroadcastStream().listen(onData);
2
Samer s Salib

Ich hatte das gleiche Problem, als ich ein Ergebnis von Observable.combineLatest2 für StreamBuilder in der Schublade verwendete:

flattern: Schlechter Zustand: Stream wurde bereits angehört.

Für mich hat die beste Lösung das Ergebnis dieses Mähdreschers zum neuen BehaviorSubject hinzugefügt und hört auf ein neues.

Vergiss nicht, den Alten zu hören !!!

class VisitsBlocc extends Object {
    Map<Visit, Location> visitAndLocation;

    VisitsBloc() {
        visitAndLocations.listen((data) {
            visitAndLocation = data;
        });
    }

    final _newOne = new BehaviorSubject<Map<Visit, Location>>();

    Stream<Map<Visit, Location>> get visitAndLocations => Observable.combineLatest2(_visits.stream, _locations.stream, (List<vis.Visit> visits, Map<int, Location> locations) {
        Map<vis.Visit, Location> result = {};

        visits.forEach((visit) {
            if (locations.containsKey(visit.skuLocationId)) {
                result[visit] = locations[visit.skuLocationId];
            }
        });

        if (result.isNotEmpty) {
            _newOne.add(result);
        }
    });
}

Ich habe .broadcast nicht verwendet, da dies meine Benutzeroberfläche verlangsamt. 

0
Serhii