La classe MyPage étend StatelessWidget { @passer outre Construction du widget (contexte BuildContext) { defaultTabController ( longueur: 2, enfant: nouveau Scaffold ( appBar: Tab. Barre. tabs: [ tab (enfant: Text ("MES INFORMATIONS"), style: TextStyle (color : Colors.black54),)), (Enfant: Text ("WEB CALENDER", style: TextStyle (color: Colors.black54),)), ], , body: PersonalInformationBlocProvider ( movieBloc: PersonalInformationBloc (), child: TabBarView ( children: [ MyInformation (), new SmallCalendarExample (), )., ) , ), ), ); } } La classe MyInformation étend StatelessWidget { // TODO: implémenter la construction var deviceSize; //Colonne1 Widget profileColumn (PersonalInformation snapshot) => Conteneur ( Height: deviceSize.height * 0.24, Child: Column ( MainAxisAlignment: MainAxisAlignment.center, Children: [ Row:. . mainAxisAlignment: MainAxisAlignment.spaceEvenly, enfants: [ Conteneur ( décoration: BoxDecoration ( borderRadius: nouveau BorderRadius.all (nouveau Radius.circular (50.0)), border: new Border.all ( couleur: Colors.black, width: 4.0, ), ), child: CircleAvatar ( backgroundImage: NetworkImage ( "http://www.binaythapa.com.np/img/me.jpg"), foregroundColor: Colors.white, backgroundColor: Couleurs.white, rayon: 40,0, ), ), ProfileTile ( Title: snapshot.firstName, Sous-titre: "Developer", ), SizedBox ( Hauteur: 10.0, ), ], ) ], ), ); Widget bodyData (instantané PersonalInformation) { return SingleChildScrollView ( child: Column ( children: [ profileColumn (instantané) ], ), ); } @passer outre Construction du widget (contexte BuildContext) { final personalInformationBloc = PersonalInformationBlocProvider.of (contexte); deviceSize = MediaQuery.of (context) .size; return StreamBuilder ( stream: personalInformationBloc.results, builder: (contexte, instantané) { if (! snapshot.hasData) return Centre ( child: CircularProgressIndicator (), ); return bodyData (snapshot.data); } ); } }
J'utilise Bloc Pattern pour récupérer des données à partir de Rest API (simplement appelé objet entier à partir de json et nom d'utilisateur analysé uniquement). La page se compose de deux onglets MyIformation et SmallCalendar. Lorsque l'application est exécutée, les données sont récupérées correctement et tout va bien. Lorsque je vais à l'onglet 2 et que je retourne à l'onglet 1, tous les écrans de l'onglet 1 deviennent rouges et affichent l'erreur: Bad state: Stream has already been listened to.
Le problème était dû au fait de ne pas disposer les contrôleurs en bloc.
void dispose() {
monthChangedController.close();
dayPressedController.close();
resultController.close();
}
La forme la plus commune de Stream
ne peut être écoutée qu'une fois à la fois. Si vous essayez d’ajouter plusieurs auditeurs, cela jettera
Mauvais état: le flux a déjà été écouté
Pour éviter cette erreur, exposez un broadcast Stream
. Vous pouvez convertir votre flux en diffusion à l'aide de myStream.asBroadcastStream
Cela doit être fait dans votre classe qui expose Stream
. Pas comme paramètre de StreamBuilder
. Étant donné que asBroadcastStream
écoute en interne le flux d'origine pour générer celui de diffusion, vous ne pouvez pas appeler cette méthode deux fois sur le même flux.
Vous devriez utiliser ce qui suit.
StreamController<...> _controller = StreamController<...>.broadcast();
J'ai eu le même problème lorsque j'ai utilisé un résultat de Observable.combineLatest2 pour StreamBuilder dans Drawer:
flutter: Mauvais état: le flux a déjà été écouté.
Quant à moi, la meilleure solution a ajouté le résultat de cette combinaison à un nouveau BehaviorSubject et à un nouveau.
N'oubliez pas d'écouter le vieil !!!
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);
}
});
}
Je n'ai pas utilisé .broadcast
car cela a ralenti mon interface utilisateur.