У меня проблема с SharedPreferences и несколькими модулями, которые я генерирую на форме, используя ListView.builder
Форма в основном запрашивает некоторые данные родителей и детали их дочерних элементов - по умолчанию форма предполагает, что родитель имеет одного дочернего элемента, но можно добавить еще несколько, нажав кнопку. ChildModule имеет возможность «закрывать», но при «повторном открытии» данные не сохраняются, поэтому, используя SharedPreferences , он отлично работает с одним дочерним элементом, но после добавления второго дочернего элемента, кажется, создавать несколько экземпляров SharedPreferences .
Я вырезал все, чтобы показать, чего я пытаюсь достичь. ПРИМЕЧАНИЕ: это используется в качестве веб-приложения, если оно имеет значение.
О, и ChildModule должен иметь свое собственное состояние, поскольку у него есть виджет, который требует его (не показан)
ЗАПРОС ФОРМА
final GlobalKey<FormBuilderState> _enquiryFormKey = GlobalKey<FormBuilderState>();
class EnquiryForm extends StatefulWidget {
static List<int> numberOfChildren = [1];
@override
_EnquiryFormState createState() => _EnquiryFormState();
}
class _EnquiryFormState extends State<EnquiryForm> {
int defaultNumberOfChildren = 1;
removeModule(){
setState(() {});
}
@override
Widget build(BuildContext context) {
return FormBuilder(
key: _enquiryFormKey,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: CustomTextField(
label: 'Parent First Name',
isRequired: true,
),
),
),
//ChildModuleList
ListView.builder(
shrinkWrap: true,
itemCount: EnquiryForm.numberOfChildren.length,
itemBuilder: (context,int index){
return ChildModule(EnquiryForm.numberOfChildren[index], removeModule);
}
),
SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
ThemedButton(
onPressed: (){
setState(() {
defaultNumberOfChildren++;
EnquiryForm.numberOfChildren.add(defaultNumberOfChildren);
});
},
child: Text(
'Add Additional Child',
style: TextStyle(color: Colors.white),)
),
SizedBox(width: 10,),
ThemedButton(
onPressed: (){},
child: Text('Enquire Now', style: TextStyle(color: Colors.white),))
],
)
],
));
}
}
МОДУЛЬ РЕБЕНКА
class ChildModule extends StatefulWidget {
final int number;
final Function() callback;
ChildModule(this.number,this.callback);
@override
_ChildModule createState() => _ChildModule();
}
class _ChildModule extends State<ChildModule> {
SharedPreferences childModuleData;
String firstName;
bool loading = true;
bool isOpen;
@override
void initState() {
print('this module number is ${widget.number}');
_spInstance();
isOpen = true;
super.initState();
}
Future<void> _spInstance() async {
if(childModuleData == null && widget.number == 1) {
childModuleData = await SharedPreferences.getInstance();
print('got instance');
} else {
print('broken');
print(childModuleData);
};
String _testValue = childModuleData.getString('Child First Name');
if(_testValue == null){
childModuleData.setString('Child First Name', '');
loading = false;
} else {
childModuleData.clear();
_spInstance();
}
}
@override
Widget build(BuildContext context) {
return loading ? Loading() : Column(
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
if (isOpen == false) {
isOpen = true;
} else {
isOpen = false;
}
});
},
child: Container(
height: 40,
padding: EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
color: Colors.blue[50],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Child Details',
style: TextStyle(color: Colors.blue[300], fontSize: 16),
),
Row(
children: <Widget>[
isOpen
? Icon(
Icons.arrow_drop_down,
size: 30,
)
: Transform.rotate(
angle: math.pi / 2,
child: Icon(
Icons.arrow_drop_down,
size: 30,
),
),
widget.number > 1
? IconButton(icon: Icon(Icons.clear), onPressed: () async {
await FormFunctions().removeModule(widget.number, EnquiryForm.numberOfChildren);
widget.callback();
})
: Container(),
],
),
],
),
),
),
AnimatedContainer(
duration: Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
padding: EdgeInsets.fromLTRB(10, 5, 10, 5),
height: isOpen ? null : 0,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300]),
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
CustomTextField(
label: fieldFirstName,
isRequired: true,
initalValue: childModuleData.getString(fieldFirstName) ?? '',
onChanged: (value){
childModuleData.setString(fieldFirstName, value);
},
),
],
),
],
),
),
],
);
}
}
ОШИБКА КОНСОЛИ ПОСЛЕ ВТОРОГО МОДУЛЯ СОЗДАНА
Launching lib/main.dart on Chrome in debug mode...
Syncing files to device Chrome...
Debug service listening on ws://127.0.0.1:58490/EkMAy9CGY74=
Debug service listening on ws://127.0.0.1:58490/EkMAy9CGY74=
this module number is 1
got instance
Instance of 'SharedPreferences'
null
this module number is 2 //Number 2 Module is created
broken
null
null
TypeError: Cannot read property 'getString' of null
at child_module._ChildModule.new._spInstance$ (http://localhost:58433/packages/webenrol/shared/widgets/day_button.dart.lib.js:3704:47)
at _spInstance$.next (<anonymous>)
at runBody (http://localhost:58433/dart_sdk.js:43121:34)
at Object._async [as async] (http://localhost:58433/dart_sdk.js:43149:7)
at child_module._ChildModule.new.[_spInstance] (http://localhost:58433/packages/webenrol/shared/widgets/day_button.dart.lib.js:3694:20)
at child_module._ChildModule.new.initState (http://localhost:58433/packages/webenrol/shared/widgets/day_button.dart.lib.js:3689:24)
at framework.StatefulElement.new.[_firstBuild] (http://localhost:58433/packages/flutter/src/widgets/widget_span.dart.lib.js:41219:58)
at framework.StatefulElement.new.mount (http://localhost:58433/packages/flutter/src/widgets/widget_span.dart.lib.js:12605:24)
at framework.SingleChildRenderObjectElement.new.inflateWidget (http://localhost:58433/packages/flutter/src/widgets/widget_span.dart.lib.js:11420:16)