getter был вызван на ноль при использовании провайдера во флаттере - PullRequest
1 голос
/ 22 февраля 2020

Я делаю приложение для флаттера, используя шаблон провайдера. И я получаю нулевую ошибку при запуске моего приложения.

button_data.dart выглядит следующим образом.

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...
}

И я хочу, чтобы эти кнопки отображались по-разному при переключении тип.

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)),
])

Но, похоже, возвращается ошибка, так как, возможно, я не установил значение по умолчанию. он говорит, что «тип получателя» был вызван на ноль «Если возможно, я хочу, чтобы« тип А »был установлен в качестве значения по умолчанию, чтобы на дисплее отображались 1, 2, 3 на кнопках.

Итак, чтобы выяснить нулевую ошибку,
Я попробовал функцию initState ниже, но это выдает больше ошибок.

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();
}

Я пытался найти похожие вопросы, но не могу найти точные вопросы, поэтому я задаю вам, ребята.

1 Ответ

0 голосов
/ 22 февраля 2020

Есть много вещей, которые вы делаете неправильно здесь. Вы должны понимать, что Поставщик может предоставлять доступ ко всем виджетам ниже. Кроме того, это также поможет другим понять Flutter и Provider немного больше.

Сначала , убедитесь, что вы открываете объект ButtonData где-то над строкой, где Вы хотите использовать значение.

Примерно так:

//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(),
        ),
      );
//}


Второй , способ, которым вы используете для получения кнопок в виджете Row очень плохо, когда вы хотите использовать свой объект несколько раз, как в вашем коде, вы должны использовать виджет Consumer, чтобы представить свои ButtonData как переменную и использовать это вместо всей строки: Provider.of<ButtonData>(context).

Проверьте это:

//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)),
    ],
  ),
);

Также, если вы выбираете значение Provider в вашей функции initState, это означает, что вы выбираете ваше значение ВНЕ дерева виджетов. (Все, что вы возвращаете в функции build, - это ваше дерево виджетов). Чтобы получить значение за пределами дерева виджетов, используйте это.

///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);

Еще один совет ... Вам не нужно использовать ключевое слово new, если вы видели это в уроках, потому что эти уроки очень старые и используют Dart 1, в настоящее время в Dart 2 ключевое слово new больше не требуется.

Надеюсь, это поможет !!

ОБНОВЛЕНИЕ:

В вашем ButtonData классе также отсутствуют объявления.

Пояснения к ошибкам, которые вы упомянули в комментарии:

//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);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...