Flutter 使用 Provider 和 Riverpod 制作表单

xen*_*s92 9 dart flutter riverpod

我是 Flutter 新手,我想升级我的代码。我有一个使用多个文本表单字段的表单,我想使用提供程序和 Riverpod 转换此代码以提高可读性,但我不确定如何执行此操作。\n对于该示例,我将代码简化为只有一个距离字段,但有很多距离字段其他的。

\n

这是我的计算器屏幕:

\n
import 'dart:async' show Future;\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:app/core/models/model_form_calculator.dart';\nimport 'package:app/core/services/service_form_validator.dart';\nimport 'package:app/core/utils/utils_app_color.dart';\n\nclass CalculatorScreen extends StatefulWidget\n{\n  CalculatorScreen({Key key}) : super(key: key);\n\n  @override\n  _CalculatorScreenState createState() => _CalculatorScreenState();\n}\n\nclass _CalculatorScreenState extends State<CalculatorScreen>\n{\n  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();\n  final _formKey = GlobalKey<FormState>();\n\n  FormCalculatorModel _formData = FormCalculatorModel();\n  bool _autoValidateForm = false;\n\n  final TextEditingController _controllerDistance = TextEditingController();\n\n  @override\n  void initState() {\n    super.initState();\n  }\n\n  @override\n  void dispose()\n  {\n    _controllerDistance.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context)\n  {\n    return GestureDetector(\n      onTap: (() => FocusScope.of(context).requestFocus(FocusNode())),\n      child: Scaffold(\n          key: _scaffoldKey,\n          backgroundColor: AppColors.colorBgDark,\n          body : _buildBody()\n      ),\n    );\n  }\n\n  Widget _buildBody()\n  {\n    return SingleChildScrollView(\n      child: Column(\n        children: [\n          Form(\n            key: _formKey,\n            autovalidate: _autoValidateForm,\n            child: Column(\n                crossAxisAlignment: CrossAxisAlignment.start,\n                children: [\n                  TextFormField(\n                    controller: _controllerDistance,\n                    keyboardType: TextInputType.number,\n                    decoration: InputDecoration(\n                      hintText: "Enter a value",\n                    ),\n                    validator: (value){\n                      return FormValidatorService.isDistanceValid(value);\n                    },\n                    onSaved: (var value) {\n                      _formData.distance = num.tryParse(value).round();\n                    },\n                  ),\n                  Row(\n                    mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                    crossAxisAlignment: CrossAxisAlignment.center,\n                    children: [\n                      Expanded(\n                        child: FlatButton(\n                            child: Text("Erase"),\n                            onPressed: _buttonResetAction\n                        ),\n                      ),\n                      Expanded(\n                        child: FlatButton(\n                            child: Text("Send"),\n                            onPressed: _buttonSubmitAction\n                        ),\n                      ),\n                    ],\n                  ),\n                ]\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n\n  void _buttonResetAction()\n  {\n    _eraseForm();\n  }\n\n  void _eraseForm(){\n    setState(() {\n      _formKey.currentState.reset();\n      _formData = FormCalculatorModel();\n      _autoValidateForm = false;\n      _controllerDistance.clear();\n    });\n  }\n\n  void _buttonSubmitAction() async\n  {\n    if (!_formKey.currentState.validate()) {\n      setState(() {\n        _autoValidateForm = true;\n      });\n      return;\n    }\n    _formKey.currentState.save();\n\n    try{\n      // some actions\n    }catch(e){\n      _eraseForm();\n      print(e.toString());\n    }\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是我的 formModel(此模型包含我可以填写表单的所有字段,并允许我存储表单的值 \xe2\x80\x8b\xe2\x80\x8b ,一旦验证,然后使用这些值进行计算\n ):

\n
\nclass FormCalculatorModel{\n  int distance;\n\n  FormCalculatorModel({\n    this.distance,\n \n  });\n\n  @override\n  String toString() {\n    return '{ '\n        '${this.distance}, '\n    '}';\n  }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

还有我的 FormValidatorService :

\n
class FormValidatorService{\n\n  static String isDistanceValid(String value)\n  {\n    num _distance = num.tryParse(value);\n    if (_distance == null) {\n      return "is required";\n    }\n    if (_distance < 200) {\n      return "Min distance is 200";\n    }\n    if (_distance > 1000) {\n      return "Max dist is 1000";\n    }\n    return null;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在我想用 Riverpod 来转换它。我有点迷失,互联网上有几个例子,我真的不知道如何管理我的表单\n起初我只是试图处理表单的验证,但它不起作用。

\n

我的计算器屏幕:

\n
import 'package:flutter/material.dart';\nimport 'package:flutter_hooks/flutter_hooks.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nclass CalculatorScreen extends HookWidget{\n\n  final _formKey = GlobalKey<FormState>();\n  bool _autoValidateForm = false;\n  FormCalculatorModel _formData = FormCalculatorModel();\n  final TextEditingController _controllerDistance = TextEditingController();\n\n  @override\n  Widget build(BuildContext context) {\n    return GestureDetector(\n      onTap: (() => FocusScope.of(context).requestFocus(FocusNode())),\n      child: Scaffold(\n          body : _buildBody(context)\n      ),\n    );\n  }\n\n  Widget _buildBody(BuildContext context){\n\n    final _formModel = useProvider(formCalculatorProvider.state);\n\n    return SingleChildScrollView(\n      child: Column(\n        children: [\n          TitleComponent(\n            title: "Calcul",\n            description: "Parametrer",\n          ),\n          ContainerComponent(\n            background: AppColors.colorBgLight,\n            children: [\n              Form(\n                key : _formKey,\n                autovalidate: _autoValidateForm,\n                child: Column(\n                  crossAxisAlignment: CrossAxisAlignment.start,\n                  children: [\n                    TextFormField(\n                      decoration: InputDecoration(\n                        labelText: "Distance",\n                        //errorText: _formModel.distance.error,\n                      ),\n                      controller: _controllerDistance,\n                      validator: (String value){\n                        return FormValidatorService.isDistanceValid(value);\n                      },\n                      onSaved: (var value) {_formData.distance = num.tryParse(value).round();}\n                    ),\n                  ],\n                ),\n              ),\n              ButtonComponent.primary(\n                  text: "Calculer",\n                  context: context,\n                  onPressed : context.read(formCalculatorProvider).submitData(key: _formKey),\n              ),\n            ],\n          )\n        ],\n      ),\n    );\n  }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

还有我的 FormCalculatorNotifier :

\n
import 'package:flutter/material.dart';\nimport 'package:hooks_riverpod/hooks_riverpod.dart';\n\nenum FormState\n{\n  EMPTY,\n  SUCCESS,\n  ERROR\n}\n\nclass FormCalculatorModelNew {\n  const FormCalculatorModelNew({this.formState, this.autoValidate, this.distance});\n  final FormState formState;\n  final bool autoValidate;\n  final String distance;\n}\n\nclass FormCalculatorNotifier extends StateNotifier<FormCalculatorModelNew>\n{\n  FormCalculatorNotifier() : super(_initial);\n\n  static const FormState _initialState = FormState.EMPTY;\n  static const _initial = FormCalculatorModelNew(\n      formState : _initialState,\n      autoValidate: false,\n      distance: null\n  );\n\n   submitData({key}){\n     print(key);\n     if (!key.currentState.validate()) {\n       state = FormCalculatorModelNew(\n           autoValidate: true,\n       );\n       return;\n     }\n     key.currentState.save();\n  }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

提供者:

\n
final formCalculatorProvider = StateNotifierProvider((ref) => FormCalculatorNotifier());\n\n
Run Code Online (Sandbox Code Playgroud)\n

小智 0

您可以使用TextEditingController

进一步创建一个像这样的提供程序,您现在可以监听文本更改并使用相同的提供程序将它们存储在需要的地方

final formControllerProvider =
StateProvider<TextEditingController>((ref) => TextEditingController());
Run Code Online (Sandbox Code Playgroud)