在flutter的initstate()之前调用了DependOnInheritedElement()

时间:2020-02-23 15:17:18

标签: flutter dart flutter-provider

我目前在提取Provider' value in初始状态时遇到问题。

我想在Appbar和正文中的其他部分的下拉菜单中设置默认值。但我说dependOnInheritedElement() was called before initstate() in flutter时出错。

我的完整代码如下

main.dart

import 'package:test_eoil/model/button_data.dart';
import 'package:test_eoil/model/output_data.dart';
import 'screen/screen.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';


void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(providers: [
//      ChangeNotifierProvider<ChordData>(create: (context) => ChordData()),
      ChangeNotifierProvider<OutputData>(create: (context) => OutputData()),
      ChangeNotifierProvider<ButtonData>(create: (context) => ButtonData())
    ],
      child: MaterialApp(
        home: Screen(),
      ),
    );
  }
}

screen.dart在屏幕文件夹中

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_eoil/model/button_data.dart';
import 'package:test_eoil/model/output_data.dart';


class Screen extends StatefulWidget {
  @override
  _ScreenState createState() => _ScreenState();
}

class _ScreenState extends State<Screen> {

  Widget dropdownWidget() {
    return DropdownButton<Button>(
      items: Provider.of<ButtonData>(context).buttons.map((Button value) {
        return new DropdownMenuItem<Button>(
          value: value,
          child: new Text(value.type.toString()),
        );
      }).toList(),
      onChanged: (Button newValue) {
        Provider.of<ButtonData>(context).setSelectedItem(newValue);
      },
      value: Provider.of<ButtonData>(context).selectedButton,
    );
  }

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


  @override
  Widget build(BuildContext context) {
    return Consumer<OutputData>(
        builder: (context, outputData, child) => Scaffold(
            appBar: AppBar(
              title: Text("${Provider.of<ButtonData>(context).selectedButton}"), // new Text(widget.title), // "${Provider.of<ButtonData>(context).selectedButton.key}"
              actions: <Widget>[
                dropdownWidget(),
              ],
            ),
            body: Column(
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  mainAxisSize: MainAxisSize.max,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Container(
                      alignment: Alignment.centerRight,
                      padding: new EdgeInsets.symmetric(
                          vertical: 24.0, horizontal: 12.0),
                      child: outputData.outputs[0].output3.length > 2
                          ? Text(
                          '${outputData.outputs[0].output3.substring(1, outputData.outputs[0].output3.length-1)}',
                          style: TextStyle(
                            fontSize: 35.0,
                            fontWeight: FontWeight.bold,
                          ))
                          : Text('${outputData.outputs[0].output3}',
                          style: TextStyle(
                            fontSize: 35.0,
                            fontWeight: FontWeight.bold,
                          )),
                    ),
                    Container(
                      alignment: Alignment.centerRight,
                      padding: new EdgeInsets.symmetric(
                          vertical: 24.0, horizontal: 12.0),
                      child: outputData.outputs[0].output2.length > 2
                          ? Text(
                          '${outputData.outputs[0].output2.substring(1, outputData.outputs[0].output2.length-1)}',
                          style: TextStyle(
                            fontSize: 35.0,
                            fontWeight: FontWeight.bold,
                          ))
                          : Text('${outputData.outputs[0].output2}',
                          style: TextStyle(
                            fontSize: 35.0,
                            fontWeight: FontWeight.bold,
                          )),
                    ),
                    Container(
                      alignment: Alignment.centerRight,
                      padding: new EdgeInsets.symmetric(
                          vertical: 24.0, horizontal: 12.0),
                      child: Text('${outputData.outputs[0].output1}',  //  outputData.outputs[0].output1
                          style: TextStyle(
                            fontSize: 35.0,
                            fontWeight: FontWeight.bold,
                          )),
                    ),
                  ],
                ),
                Expanded(
                  child: new Divider(),
                ),
                Column(children: [
                  Row(children: [
                    buildButton("CLEAR"),
                    buildButton(""),
                    buildButton("PLAY"),
                    //                    buildButton("/")
                  ]),
                ])
              ],
            )));
  }



  Widget buildButton(String buttonText) {
    return new Expanded(
      child: new OutlineButton(
        padding: new EdgeInsets.all(30.0),
        child: new Text(
          buttonText,
          style: TextStyle(fontSize: 20.0),
        ),
        onPressed: () => print("test"),
      ),
    );
  }
}

button_data.dart在模型文件夹中

import 'package:flutter/foundation.dart';
//import 'dart:collection';

class Button {
  final int id;
  final String type;
  final String numberone;
  final String numbertwo;
  final String numberthree;

  Button({this.id, this.type, this.numberone, this.numbertwo, this.numberthree});


}

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

  List<Button> get buttons => _buttons;
  Button _selectedButton;
  Button get selectedButton => _selectedButton;

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


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

  Button getKey(String value) {
    return _buttons
        .where((button) => button.type == value).first;
  }

  String getNumberOne(String value) {
    return _buttons
        .where((button) => button.type == value)
        .map((button) => (button.numberone))
        .toString();
  }

  String getNumberTwo(String value) {
    return _buttons
        .where((button) => button.type == value)
        .map((button) => (button.numbertwo))
        .toString();
  }

  String getNumberThree(String value) {
    return _buttons
        .where((button) => button.type == value)
        .map((button) => (button.numberthree))
        .toString();
  }

}

output_data.dart在模型文件夹中

import 'package:flutter/foundation.dart';


class Output {

  final int id;
  String output1;
  String output2;
  String output3;

  Output({this.id, this.output1, this.output2, this.output3});

}


class OutputData extends ChangeNotifier {

  List<Output> _outputs = [
    Output(output1: 'Hello', output2: 'Hi', output3: 'Nice'),
    Output(output1: 'Haha', output2: 'Bye', output3: 'Sad'),
  ];

  List<Output> get outputs {
    return _outputs;
  }


}

说实话,我希望在没有initstate()的情况下也能正常工作(我听说提供程序模式不需要稳定)

我想出一个initstate()的原因是,这是唯一在提供程序中设置默认值的解决方案(据我所知)。

希望你们能帮助我!


问题可以通过在button_data.dart中添加Button_data构造函数来解决。

ButtonData () {
    _selectedButton = _buttons.first;
  }

1 个答案:

答案 0 :(得分:11)

我在先前的回答中还提到Provider.of(context)应该在小部件树中使用,而build()方法之外的任何内容都不在小部件树中。但是,如果仍然要使用它,则需要将listen参数设置为false

像这样:

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

但是正如您在问题中提到的那样,您不想使用initState来设置默认值。在每种编程语言中,当您声明带有值的变量时,该值将成为其初始值/默认值,以后可以进行更改。

您可以在initState类中编辑以下内容,而不使用ButtonData

//Remove this.
List<Button> get buttons => _buttons;
  Button _selectedButton;
  Button get selectedButton => _selectedButton;

//Instead, Use this.
List<Button> get buttons => _buttons;
Button _selectedButton = _buttons.first;
Button get selectedButton => _selectedButton;

//This will declare the `selectedButton` variable with a default value.
//Happy coding! :)