在颤振中在 initstate() 之前调用了dependOnInheritedElement()
Posted
技术标签:
【中文标题】在颤振中在 initstate() 之前调用了dependOnInheritedElement()【英文标题】:dependOnInheritedElement() was called before initstate() in flutter 【发布时间】:2020-06-07 08:38:19 【问题描述】:我目前在获取 Provider' value in
initstate 时遇到问题。
我想在 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()
的情况下工作(我听说提供者模式不需要stful)
我提出initstate()
的原因是这是唯一的解决方案(据我所知)在提供程序中设置默认值。
希望大家帮帮我!
通过在button_data.dart
中添加 Button_data 构造函数解决了问题。
ButtonData ()
_selectedButton = _buttons.first;
【问题讨论】:
【参考方案1】:我在之前的回答中还提到,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
设置默认值。在每种编程语言中,当您声明一个带有值的变量时,该值将成为它的初始/默认值,您可以稍后更改它。
您可以在ButtonData
类中编辑以下内容,而不是使用initState
。
//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! :)
【讨论】:
我在initial value
中将listen参数设置为false
。返回相同的错误。你可以检查一下,因为我上传了完整的代码。
第二种方式——用button_data.dart
中的值声明一个变量。——这就是我最初的意图。但是当我用你所说的值声明一个变量时,错误返回Only static members can be accessed in initializers
。我上传了完整的代码,你也可以检查一下。
如果可能,我想修复第二个问题only static member...
。但据我所知,这很难解决。这就是为什么我试图以不同的方式绕过它。
问题已解决。我刚刚编辑了我的块。真的感谢您看我的问题。 @BasedMusa以上是关于在颤振中在 initstate() 之前调用了dependOnInheritedElement()的主要内容,如果未能解决你的问题,请参考以下文章
将文档中的值从数据库保存到 initState 值的颤振问题
未处理的异常:在 _ScreenState.initState() 完成之前调用了 inheritFromWidgetOfExactType(_LocalizationsScope) 或 inheri