【问题标题】:How to pass a notifyListeners method to an onPressed button function?如何将 notifyListeners 方法传递给 onPressed 按钮功能?
【发布时间】:2021-01-25 00:27:58
【问题描述】:

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

首先:一旦用户在两个文本表单字段中都键入了内容,它应该为我的 LoginButton 小部件提供一个 onPressed 方法。一旦将 onPressed 函数分配给按钮,该类就会调用 notifyListeners() 方法。

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

问题是我不知道如何实现 onPressed 方法,以便在用户触发 onPressed 方法后让 Consumer 小部件自行重建。我认为一旦用户按下按钮 就永远不会调用 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();
    }
  }
}

【问题讨论】:

  • 到目前为止我发现我的 LoginButton 小部件永远不会重建。我的结论是 notifyListeners() 方法一旦通过就永远不会从 LoginButton 内部调用。你能解释一下我怎么能做到这一点吗?也许我应该传递一个处理函数?但是在这种情况下该怎么做呢?

标签: flutter dart button provider flutter-onpressed


【解决方案1】:

我认为问题在于这个方法永远不会被调用,因为onPressed 处理程序位于ChangeNotifier 内部。 这是完全错误的方法。不要在ChangeNotifier 中传递像FocusNodecontextvalidator 这样的Widget 逻辑实例,而是在按钮的onPressed 处理程序中进行所有验证,然后使用@987654329 在通知程序中调用该方法@。

...
  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();
        }
    );

  } 




还有LoginButtonProvider

class LoginButtonProvider with ChangeNotifier {

  TokenViewModel _tokenViewModel = new TokenViewModel();

  bool _isLoading = false;


  get isLoading => _isLoading;

  void updateButton(String email, String password)async {
          _isLoading = true; 
           notifyListeners();

           await _tokenViewModel.getToken(email ,password); /// not sure what this is, but if its an API call would not recommend passing in context and node again,

          _isLoading = false;
          notifyListeners();
    }

确保您的MaterialApp 上方有ChangeNotifierProvider&lt;LoginButtonProvider&gt; 以通过Provider 访问。

【讨论】:

  • 非常感谢您花时间检查我的问题。我明白你在说什么。我正在阅读有关 MVVM 代码架构的信息。他们指出所有业务逻辑都应该在小部件 UI 之外。我有带有这些参数的 updateButton 方法,因为我想在小部件 UI 之外分配 onPressed 方法。如果我将所有内容都放在小部件中,则代码看起来很臃肿。我设法通过在 getToken() 方法中调用 notifyListeners() 来让我的代码工作,并且我刚刚在表单字段中注册了一个新的监听器。
  • 我也关注 MVVM,按照业务逻辑可能是 API 调用和状态管理,但我认为验证应该发生在 UI 层本身。您甚至可以在表单中找到验证器。因此,只有值必须传递到下一层,而不是小部件或类的实例。特别是在颤动的情况下,您将太多不必要的东西传递给ChnageNotifier,例如上下文和焦点节点,其生命周期应保留在小部件层中。所以我想说我的解决方案是更好的方法,因为我已经关注了很长一段时间了。它工作得非常好@AleksaVujisic
  • 我当然同意你的看法!在阅读了有关 MVVM 的更多信息后,我现在更好地理解了它。您的答案的问题是该按钮始终具有 onPressed 功能。而且我希望在我的表单中的两个文本字段都有来自用户的输入文本之前,该按钮不可点击。
  • @AleksaVujisic,这不是问题,您可以添加一个三元运算符以使按钮不可点击。让我编辑我的答案。查看this 博客文章,使用providerChangeNotifier 深入了解MVVM
  • 非常感谢!我改变了我使用 MVVM 的方式,我这样做了,它更有条理,整体更好!我会接受你的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-28
  • 2020-03-09
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多