Flutter 如何将notifyListeners方法传递给onPressed按钮函数?

Flutter 如何将notifyListeners方法传递给onPressed按钮函数?,flutter,dart,button,provider,flutter-onpressed,Flutter,Dart,Button,Provider,Flutter Onpressed,我有一个LoginButtonProvider类,该类有两个用途 第一:一旦用户输入了两个文本表单字段,它应该为我的LoginButton小部件提供一个onPressed方法。一旦将onPressed函数分配给按钮,该类将调用notifyListeners()方法 第二:一旦用户按下该按钮并调用onPressed方法,它应该在该按钮内创建一个旋转圈。一旦用户按下按钮,它还应该调用notifyListeners(),以便将布尔标志_isLoading设置为true 问题是,我不知道如何实现onPr

我有一个LoginButtonProvider类,该类有两个用途

第一:一旦用户输入了两个文本表单字段,它应该为我的LoginButton小部件提供一个onPressed方法。一旦将onPressed函数分配给按钮,该类将调用notifyListeners()方法

第二:一旦用户按下该按钮并调用onPressed方法,它应该在该按钮内创建一个旋转圈。一旦用户按下按钮,它还应该调用notifyListeners(),以便将布尔标志_isLoading设置为true

问题是,我不知道如何实现onPressed方法,以便在用户触发onPressed方法后,消费者小部件能够重建自身。我认为,一旦用户按下按钮,就不会调用notifyListeners,因此按钮上不会出现旋转圈,但它应该会出现 我还尝试将引用发送到notifyListeners方法。在onPressed函数中调用notifyListeners()时,小部件不会重新构建自身。为什么呢? 非常感谢你的帮助

这是LoginButtonProvider类

class LoginButtonProvider with ChangeNotifier {

  TokenViewModel _tokenViewModel = new TokenViewModel();
  Function _onPressed;
  bool _isLoading = false;

  get onPressed => _onPressed;
  get isLoading => _isLoading;

  void updateButton(BuildContext context, FocusNode focusNode, Validator validator) {
    if (!validator.areFieldsEmpty()) {
      _onPressed = () {
        if (validator.validateFields()) {
          _isLoading = true;
          notifyListeners();
          _tokenViewModel.getToken(validator.email, validator.password, context, focusNode);
          _isLoading = false;
          notifyListeners();
        } else {
          SimpleShowDialog.createSimpleShowDialog(
            title: "Invalid Input",
            buttonText: "OK",
            context: context,
            message: validator.errorMessage,
            focusNode: focusNode,
          );
          validator.reset();
        }
      };
      notifyListeners();
    } else {
      _onPressed = null;
      notifyListeners();
    }
  }
}

我认为问题在于,从未调用此方法,因为
onPressed
处理程序位于
ChangeNotifier
中。 这完全是错误的做法。不要在
ChangeNotifier
中传递小部件逻辑实例,如
FocusNode
context
validator
,而是在按钮的
onPressed
处理程序中执行所有验证,然后使用
提供程序调用通知程序中的方法

...
  Widget build(BuildContext context){
   final login = Provider.of<LoginButtonProvider>(context);
   
    return login.isLoading? 
    Center(child: CircularProgressIndicator()):
    Flatbutton(
    child: Text('Login')
    onPressed : 
         validator.areFieldsEmpty()) ?  /// Now the button should not be clickbale, till the field is filled.
         null:
         () {
      // do all your validation here
        if (!validator.areFieldsEmpty()) {

          login.updateButton(validator.email, validator.password);      

          } else {

          SimpleShowDialog.createSimpleShowDialog(
            title: "Invalid Input",
            buttonText: "OK",
            context: context,
            message: validator.errorMessage,
            focusNode: focusNode,
          );
          validator.reset();
        }
    );

  } 





确保您的
MaterialApp
上方有
ChangeNotifierProvider
可通过
提供者访问
。我的结论是,一旦传入notifyListeners()方法,就不会从LoginButton内部调用它。你能解释一下我是如何做到这一点的吗?也许我应该传递一个处理函数?但是在这种情况下怎么做呢?非常感谢你抽出时间来检查我的问题。我明白你在说什么。我在读关于MVVM代码体系结构的书。他们指出,所有业务逻辑都应该在小部件UI之外。我有带有这些参数的updateButton方法,因为我想在小部件UI之外分配onPressed方法。如果我把所有的东西都放在小部件中,代码看起来就会膨胀。我通过在getToken()方法中调用notifyListeners()使代码正常工作,我刚刚在表单字段中注册了一个新的侦听器。我也遵循MVVM,根据业务逻辑,它可能是API调用和状态管理,但我认为验证应该发生在UI层本身。您甚至可以在表单中找到验证器。因此,只有值必须传递到下一层,而不是小部件或类的实例。特别是在flatter的情况下,您正在将太多不必要的内容传递到
ChnageNotifier
,比如上下文和焦点节点,它们的生命周期应该在小部件层中。所以我想说,我的解决方案是更好的方法,因为我已经遵循了一段时间了。它运行得非常好@Aleksavujisic我当然同意你的观点!在阅读了更多关于MVVM的内容后,我现在对它有了更好的理解。你回答的问题是,按钮总是具有ON按下功能。我希望在表单中的两个文本字段都有用户输入的文本之前,按钮不可单击。@AleksaVujisic,这不是问题,您可以添加三元运算符使按钮不可单击。让我编辑我的答案。使用
provider
ChangeNotifier
查看博客文章,深入了解MVVM,非常感谢!我改变了我使用MVVM的方式,我这样做了,它更有条理,整体上更好!我会接受你的回答!
...
  Widget build(BuildContext context){
   final login = Provider.of<LoginButtonProvider>(context);
   
    return login.isLoading? 
    Center(child: CircularProgressIndicator()):
    Flatbutton(
    child: Text('Login')
    onPressed : 
         validator.areFieldsEmpty()) ?  /// Now the button should not be clickbale, till the field is filled.
         null:
         () {
      // do all your validation here
        if (!validator.areFieldsEmpty()) {

          login.updateButton(validator.email, validator.password);      

          } else {

          SimpleShowDialog.createSimpleShowDialog(
            title: "Invalid Input",
            buttonText: "OK",
            context: context,
            message: validator.errorMessage,
            focusNode: focusNode,
          );
          validator.reset();
        }
    );

  }