I am currently having an issue while fetching a Provider' value in
initstate`.
I want to set a default value in dropdown in an Appbar and other parts in body. But I got an error saying dependOnInheritedElement() was called before initstate() in flutter
.
My full code is below
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
in screen folder
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
in model folder
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
in model folder
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;
}
}
To be honest, I want to make it work without initstate()
if possible(I heard that provider pattern doesn't need stful)
The reason I come up with an initstate()
is this is the only solution (as much as I know) to set the default value in provider.
Hope you guys help me!
Issue is solved by adding Button_data constructor in button_data.dart
.
ButtonData () {
_selectedButton = _buttons.first;
}
See Question&Answers more detail:
os