Comment valeur réglée correctement de DropDownButton à l'aide du Bloc à Flutter?

voix
2

Je suis nouveau dans le modèle de programmation du Bloc et je vais avoir un problème lors de son utilisation avec Dropdown C'est dans ma classe de bloc:

final _dropDown = BehaviorSubject<String>();
Stream<String> get dropDownStream => _dropDown.stream;
Sink<String> get dropDownSink => _dropDown.sink;
final _dropdownValues = BehaviorSubject<List<String>>(seedValue: [
    'One',
    'Two',
    'Three',
    'Four',
  ].toList());
  Stream<List<String>> get dropdownValuesStream => _dropdownValues.stream;

Dans ma page widget j'ai ajouté le widget déroulant suivant afin que tout est géré par la classe du Bloc:

StreamBuilder<List<String>>(
                      stream: _exampleBloc.dropdownValuesStream,
                      builder: (BuildContext contextValues, AsyncSnapshot snapshotValues) {
                        return StreamBuilder<String>(
                            stream: _exampleBloc.dropDownStream,
                            builder: (BuildContext context, AsyncSnapshot snapshot) {
                              return InputDecorator(
                                decoration: InputDecoration(
                                  icon: const Icon(Icons.color_lens),
                                  labelText: 'DropDown',
                                ),
                                child: DropdownButtonHideUnderline(
                                  child: DropdownButton<String>(
                                    value: snapshot.data,
                                    onChanged: (String newValue) => _exampleBloc.dropDownSink.add(newValue),
                                    items: snapshotValues.data != null ? snapshotValues.data.map<DropdownMenuItem<String>>((String value) {
                                      return DropdownMenuItem<String>(
                                        value: value,
                                        child: Text(value),
                                      );
                                    }).toList() : <String>[''].map<DropdownMenuItem<String>>((String value) {
                                      return DropdownMenuItem<String>(
                                        value: value,
                                        child: Text(value),
                                      );
                                    }).toList(),
                                  ),
                                ),
                              );
                            },
                          );
                      },
                    ),

Mais faire comme ça, je reçois cette erreur lors de la mise à la valeur (valeur: snapshot.data) du DropDownButton:

I/flutter ( 5565): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 5565): The following assertion was thrown building StreamBuilder<String>(dirty, state:
I/flutter ( 5565): _StreamBuilderBaseState<String, AsyncSnapshot<String>>#70482):
I/flutter ( 5565): 'package:flutter/src/material/dropdown.dart': Failed assertion: line 514 pos 15: 'items == null ||
I/flutter ( 5565): value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1': is not
I/flutter ( 5565): true.
I/flutter ( 5565):
I/flutter ( 5565): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 5565): more information in this error message to help you determine and fix the underlying cause.
I/flutter ( 5565): In either case, please report this assertion by filing a bug on GitHub:
I/flutter ( 5565):   https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 5565):
I/flutter ( 5565): When the exception was thrown, this was the stack:
I/flutter ( 5565): #2      new DropdownButton (package:flutter/src/material/dropdown.dart:514:15)
I/flutter ( 5565): #3      _ExamplePageState.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:financeiro_mobile/src/ui/exemple/example_page.dart:129:42)
I/flutter ( 5565): #4      StreamBuilder.build (package:flutter/src/widgets/async.dart:423:74)
I/flutter ( 5565): #5      _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:125:48)
I/flutter ( 5565): #6      StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
I/flutter ( 5565): #7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
I/flutter ( 5565): #8      Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
I/flutter ( 5565): #9      StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
I/flutter ( 5565): #10     Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
I/flutter ( 5565): #11     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
I/flutter ( 5565): #12     Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
I/flutter ( 5565): #13     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
I/flutter ( 5565): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
I/flutter ( 5565): #15     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
I/flutter ( 5565): #16     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter ( 5565): #17     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter ( 5565): #18     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter ( 5565): #19     _invoke (dart:ui/hooks.dart:154:13)
I/flutter ( 5565): #20     _drawFrame (dart:ui/hooks.dart:143:3)
I/flutter ( 5565): (elided 2 frames from class _AssertionError)

J'ai essayé beaucoup d'idées comme vérifier si snapshotValues.data est pas nul lors de la configuration. Je sais que la valeur doit être quelque chose dans la liste ou nulle. Mais pas logique que je mets il fait cette erreur disparaître. Si je mets la valeur null, cela fonctionne, mais la valeur sélectionnée ne montre pas. Est-ce que je fais ce mal? Y at-il une meilleure façon qui fonctionne? Comment puis-je résoudre ce problème? Merci!

Créé 19/12/2018 à 14:11
source utilisateur
Dans d'autres langues...                            


2 réponses

voix
0

Je résolu à l'aide de deux flux dans le bloc, une pour la liste des elemtns et l'autre pour la valeur. Donc ther construire, vous avez besoin de deux StreamBuilders chaînés et quand u got les deux instantanés avec des données, vous chargez la construction. Comme ça:

Widget _holdingDropDown() {
return StreamBuilder(
    stream: bloc.holding,
    builder: (BuildContext context, AsyncSnapshot<Holding> snapshot) {
      return Container(
        child: Center(
          child: snapshot.hasData
              ? StreamBuilder(
                  stream: bloc.obsHoldingList,
                  builder: (BuildContext context,
                      AsyncSnapshot<List<Holding>> holdingListSnapshot) {
                    return holdingListSnapshot.hasData ?
                    DropdownButton<Holding>(
                      value: snapshot.data,
                      items: _listDropDownHoldings,
                      onChanged: (Holding h) {
                        _changeDropDownItemHolding(h);
                      },
                    ): CircularProgressIndicator();
                  },
                )
              : CircularProgressIndicator(),
        ),
      );
    });
}

J'utilise l'indicateur de progression circulaire pour revenir si je n'ai pas l'instantané des données. J'espère avoir été utile.

Créé 19/03/2019 à 00:48
source utilisateur

voix
0

C'est parce que vous utilisez un StreamBuilder, donc à la première fois votre instantané est vide, vous devez faire une validation:

        return snapshot.hasData ? 
             InputDecorator(
                                        decoration: InputDecoration(
                                          icon: const Icon(Icons.color_lens),
                                          labelText: 'DropDown',
                                        ),
                                        child: DropdownButtonHideUnderline(
                                          child: DropdownButton<String>(
                                            value: snapshot.data,
                                            onChanged: (String newValue) => _exampleBloc.dropDownSink.add(newValue),
                                            items: snapshotValues.data != null ? snapshotValues.data.map<DropdownMenuItem<String>>((String value) {
                                              return DropdownMenuItem<String>(
                                                value: value,
                                                child: Text(value),
                                              );
                                            }).toList() : SizedBox(height: 0.0)
                                        ),
                                      ) : SizedBox(height: 0.0);

Afficher un widget de vide SizedBox(height: 0.0)ouCircleProgressIndicator

Créé 19/12/2018 à 14:25
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more