web-dev-qa-db-fra.com

Getter a été appelé sur NULL lors de l'utilisation d'un fournisseur en flutter

Je fais une application flottante à l'aide de motif de fournisseur. Et je reçois une erreur nulle lorsque je lance mon application.

Button_Data.Dart va comme ça.

class ButtonData extends ChangeNotifier {
  List<Button> _buttons = [
    Button(
        type: "A",
        numberone: "1",
        numbertwo: "2",
        numberthree: "3",
    ),
    Button(
        key: "B",
        numberone: "A",
        numbertwo: "B",
        numberthree: "C",
    ),
  ];

  Button _selectedButton;

  List<Button> get buttons => _buttons;

  Button get selectedButton => _selectedButton;

  void setSelectedItem(Button s) {
    _selectedButton = s;
    notifyListeners();
  }


 Button getType(String value) {
    return _buttons
        .where((button) => button.type == value).first;
  } // it is no use...
}

Et je veux que ce bouton affiche de manière difforme lorsque j'ai changé de type.

new Row(children: [
  buildButton(Provider.of<ButtonData>(context).getNumberOne(Provider.of<ButtonData>(context).selectedButton.type)),
  buildButton(Provider.of<ButtonData>(context).getNumberTwo(Provider.of<ButtonData>(context).selectedButton.type)),
  buildButton(Provider.of<ButtonData>(context).getNumberThree(Provider.of<ButtonData>(context).selectedButton.type)),
])

Mais l'erreur semble être retournée depuis peut-être que je ne définis pas la valeur par défaut. Il est écrit "Le type de getter 'a été appelé sur NULL' si possible, je souhaite que" Type A "soit définie comme valeur par défaut de sorte que l'affichage indique 1, 2, 3 sur les boutons.

Donc, pour comprendre l'erreur nulle,
[.____] J'ai essayé la fonction initState ci-dessous, mais que cela jette plus d'erreurs.

1. There isn't a setter named 'selectedButton' in class 'ButtonData'

2. The expression here has a type of void and therefore can't be used

@override
void initState() {
  Provider.of<ButtonData>(context).selectedButton = Provider.of<ButtonData>(context).setSelectedItem(Provider.of<ButtonData>(context).buttons.first);
  super.initState();
}

J'essaie de trouver des questions similaires, mais je ne trouve pas les questions exactes pour que je vous demande les gars.

3
Brooklyn Lee

Il y a beaucoup de choses que vous faites mal ici. Vous devez comprendre que le fournisseur peut exposer à tous les widgets en dessous. De plus, cela aidera également les autres à comprendre Flutter et Provider un peu plus.

premier de tous, assurez-vous d'exposer l'objet ButTondata de quelque part au-dessus de la ligne où vous souhaitez utiliser la valeur.

Comme:

//You can use this in the build method, and wrap it on top of your page Scaffold. 

//@override
//Widget build(BuildContext context) {
return ChangeNotifierProvider(
        create: (_) => ButtonData(),
        child: Scaffold(
          appBar: _appBar(),
          body: _body(),
        ),
      );
//}


[.____] second, la façon dont vous utilisez pour obtenir des boutons dans le widget Row est très mauvais, lorsque vous souhaitez utiliser votre objet plusieurs fois comme dans votre code, vous Devrait utiliser le widget Consumer pour exposer vos boutons comme une variable et utilisez-le à la place de la ligne complète: Provider.of<ButtonData>(context).

Vérifiez ceci:

//WRONG WAY
new Row(children: [
  buildButton(Provider.of<ButtonData>(context).getNumberOne(Provider.of<ButtonData>(context).selectedButton.type)),
  buildButton(Provider.of<ButtonData>(context).getNumberTwo(Provider.of<ButtonData>(context).selectedButton.type)),
  buildButton(Provider.of<ButtonData>(context).getNumberThree(Provider.of<ButtonData>(context).selectedButton.type)),
])

//CORRECT WAY
Consumer<ButtonData>(
  builder: (BuildContext context, ButtonData buttonData, Widget child) => Row(
    children: <Widget>[
      buildButton(buttonData.getNumberOne(buttonData.selectedButton.type)),
      buildButton(buttonData.getNumberTwo(buttonData.selectedButton.type)),
      buildButton(buttonData.getNumberThree(buttonData.selectedButton.type)),
    ],
  ),
);

De plus, si vous recherchez une valeur Provider dans votre fonction initState, cela signifie que vous recherchez votre valeur en dehors de l'arborescence du widget. (Quoi que vous reveniez dans votre fonction build est votre arborescence de widget). Pour chercher une valeur en dehors de l'arborescence du widget, utilisez ceci.

///WRONG
Provider.of<ButtonData>(context).selectedButton = Provider.of<ButtonData>(context).setSelectedItem(Provider.of<ButtonData>(context).buttons.first);

///CORRECT
///You need to set `listen` to false.
Provider.of<ButtonData>(context, listen: false).selectedButton = Provider.of<ButtonData>(context, listen: false).setSelectedItem(Provider.of<ButtonData>(context, listen: false).buttons.first);

///BETTER
ButtonData buttonData = Provider.of<ButtonData>(context, listen: false);
buttonData.selectedButton = buttonData.setSelectedItem(buttonData.buttons.first);

n autre conseil ... Vous n'avez pas besoin d'utiliser new mot-clé, si vous l'avez vu dans des tutoriels, c'est parce que ces tutoriels sont très anciens et utilisent Dart 1, actuellement à Dart 2, le mot-clé new n'est plus nécessaire.

J'espère que cela vous aidera !!

Mise à jour :

Vous avez également des déclarations manquantes dans votre classe ButtonData.

Explications pour les erreurs que vous avez mentionnées dans le commentaire:

//If you want to use the following:
Provider.of<ButtonData>(context, listen: false).selectedButton = xyz;

//You need to declare a setter named `selectedButton` in your ButtonData
// class. Like so:

set selectedButton(Button button) {
    _selectedButton = button;
    notifyListeners();
}

//Currently, in your ButtonData class, you have not declared a setter,
// instead you created a method there for updating the value. 
//This one.

void setSelectedItem(Button s) {
    _selectedButton = s;
    notifyListeners();
}

//If you want to use this method for updating your `selectedButton` value,
// you can use the following line of code.
Provider.of<ButtonData>(context, listen: false).setSelectedItem(xyz);

0
BasedMusa

Pour la plupart des cas, vous pouvez le réparer juste en utilisant le Statefull.mounted biens.

initState() {
  if (mounted) {
    context.read<YouType>();
  }

  super.initState();
}
1
e200