Flutter:共享首选项的多个实例?

时间:2020-04-19 05:50:02

标签: flutter sharedpreferences flutter-web

我在使用SharedPreferences在表单上生成的ListView.builder和多个模块有问题

该表单基本上是在询问一些父母的详细信息以及他们的孩子的详细信息-默认情况下,该表单假定父母有一个孩子,但是可以通过单击按钮添加更多。 ChildModule可以“关闭”,但是当“重新打开”时数据不会持久,因此使用SharedPreferences可以对一个Child正常工作,但是一旦添加了另一个Child似乎就可以了SharedPreferences的多个实例。

我已经删减了所有内容以显示我要实现的目标。注意,如果有必要,它将用作Web应用程序。

Oh和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)

1 个答案:

答案 0 :(得分:0)

在您的情况下,您所关心的是在共享首选项中记录数据的级别。一种解决方案是在密钥中添加小部件编号,例如(await SharedPreferences.getInstance()).setString("Your Key${widgetNumber}"); 并编辑您的函数_spInstance

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

  Future<void> _spInstance() async {
    if(childModuleData == null) {
      childModuleData = await SharedPreferences.getInstance();
      print('got instance');
    }
    String _testValue = childModuleData.getString('Child First Name${widget.number}');
    //NB: do not clear data on chlidModuleData any more.
    ...

  }

  ...

}