微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

FLUTTER MOBX:构建函数返回null相关的引起错误的小部件是Observer

如何解决FLUTTER MOBX:构建函数返回null相关的引起错误的小部件是Observer

我正在尝试使用 MOBX 在两个字段(电子邮件和密码)中进行验证,并且正在 compuntig 中计算两个函数的结果。名为formIsValid,但mobX向我返回了此错误一个构建函数返回了null。 相关的引起错误的小部件是 观察者

我尝试用不同的方式来做,但我做不到,而且我的电子邮件观察对象 emailErrorLabel passwordErrorLabel 不会影响 TextTormField errorText。

这是我的代码viewmodel:

import 'package:covid_app/app/service/firebase/firebase_auth.dart';
import 'package:covid_app/app/service/firebase/firebase_auth_impl.dart';
import 'package:covid_app/app/ui/home/home_page.dart';
import 'package:Flutter/material.dart';
import 'package:mobx/mobx.dart';

part 'login_viewmodel.g.dart';

class Loginviewmodel = LoginviewmodelBase with _$Loginviewmodel;

abstract class LoginviewmodelBase with Store {
  @observable
  String email = "";

  @observable
  String password = "";

  @observable
  bool error = false;

  @observable
  bool emailErrorLabel = false;

  @observable
  bool passwordErrorLabel = false;

  final _auth = Auth();

  @action
  changeEmail(String newEmail) => email = newEmail;

  @action
  changePassword(String newPassword) => password = newPassword;

  @action
  setHasErrorOnEmail(bool value) => emailErrorLabel = value;

  @action
  setHasErrorOnPassword(bool value) => passwordErrorLabel = value;

  bool emailIsValid() {
    if (email.isNotEmpty && email.contains("@")) {
      return true;
    } else {
      setHasErrorOnEmail(true);
      return false;
    }
  }

  bool passwordisValid() {
    if (password.isNotEmpty || password.length >= 8) {
      return true;
    } else {
      setHasErrorOnPassword(true);
      return false;
    }
  }

  @computed
  bool get formIsValid {
    return emailIsValid() && passwordisValid();
  }

  @action
  Future<void> firebaseLogin(dynamic context) async {
    try {
      if (email.isNotEmpty && password.isNotEmpty) {
        var userId;
        await _auth.signIn(email,password).then((value) => userId = value);
        userId.length > 0 ? homeNavigator(context) : error = true;
      } else {
        error = true;
      }
    } catch (Exception) {
      error = true;
      print("Login Error: $Exception");
    }
  }

  void homeNavigator(context) {
    Navigator.push(
        context,MaterialPageRoute(builder: (context) => HomePage()));
  }
}

我的登录页面

import 'package:covid_app/app/ui/login/login_viewmodel.dart';
import 'package:covid_app/app/widgets/KeyboardHideable.dart';
import 'package:covid_app/core/constants/colors.dart';
import 'package:covid_app/core/constants/dimens.dart';
import 'package:covid_app/core/constants/string.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:Flutter/material.dart';
import 'package:Flutter_mobx/Flutter_mobx.dart';
import '../../widgets/button_component.dart';
import 'widgets/text_form_field_component.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  var vm = Loginviewmodel();
  var value = zero;
  var valueTextFields = sixtyEight;
  TextEditingController controllerEmail = TextEditingController();
  TextEditingController controllerPassword = TextEditingController();

  void animatedtest() async {
    Future.delayed(Duration(seconds: 0),() {
      setState(() {
        value = sixtyEight;
        valueTextFields = zero;
      });
    });
  }

  @override
  void initState() {
    super.initState();
    animatedtest();
  }

  @override
  Widget build(BuildContext context) {
    return KeyboardHideable(
      child: Scaffold(
        backgroundColor: darkPrimaryColor,body: SingleChildScrollView(
          child: Container(
            height: MediaQuery.of(context).size.height,child: SafeArea(
              child: Center(
                child: Padding(
                  padding: const EdgeInsets.all(sixteen),child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
                      Expanded(
                        child: Card(
                          elevation: twelve,shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.all(Radius.circular(twentyFour)),),child: Padding(
                            padding: const EdgeInsets.all(thirtyTwo),child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
                                Spacer(),Expanded(
                                  flex: 8,child: AnimatedContainer(
                                      margin: EdgeInsets.only(bottom: value),duration: Duration(seconds: 1),child: Image.asset(
                                          "assets/images/logo_covid_app.png")),Expanded(
                                  flex: 7,child: AnimatedContainer(
                                    margin:
                                        EdgeInsets.only(top: valueTextFields),child: Column(
                                      children: <Widget>[
                                        Expanded(
                                          flex: 2,child: Observer(
                                            builder: (_) =>
                                                TextFormFieldComponent(
                                                    emailHintText,false,controllerEmail,vm.changeEmail,vm.emailErrorLabel,emailErrorLabel),Expanded(
                                          flex: 2,child: Observer(builder: (_) {
                                            return TextFormFieldComponent(
                                                passwordHintText,true,controllerPassword,vm.changePassword,passwordErrorLabel);
                                          }),],SizedBox(
                                  height: twentyEight,Expanded(
                                  flex: 2,child: Observer(
                                    builder: (_) => ButtonComponent(
                                      title: loginButtonLabel,fillColor: rosePrimaryColor,textColor: Colors.white,loginFun: vm.formIsValid
                                          ? () => vm.firebaseLogin(context)
                                          : null,SizedBox(
                                  height: twenty,child: ButtonComponent(
                                      title: registerButtonLabel,fillColor: darkPrimaryColor,loginFun: () {}),Spacer()
                              ],);
  }
}

我的TextFormField组件:

import 'package:covid_app/core/constants/colors.dart';
import 'package:covid_app/core/constants/dimens.dart';
import 'package:Flutter/material.dart';

// ignore: must_be_immutable
class TextFormFieldComponent extends StatefulWidget {
  String hintText;
  bool hideText;
  TextEditingController genericControler;
  bool genericValidation;
  String errorMessage;
  Function onChangedGeneric;

  TextFormFieldComponent(this.hintText,this.hideText,this.genericControler,this.onChangedGeneric,this.genericValidation,this.errorMessage);

  @override
  _TextFormFieldComponentState createState() => _TextFormFieldComponentState();
}

class _TextFormFieldComponentState extends State<TextFormFieldComponent> {
  @override
  Widget build(BuildContext context) {
    return Theme(
      data:
          ThemeData(cursorColor: rosePrimaryColor,hintColor: darkPrimaryColor),child: TextFormField(
        onChanged: widget.onChangedGeneric,controller: widget.genericControler,obscureText: widget.hideText,decoration: Inputdecoration(
          hintText: widget.hintText,errorText: widget.genericValidation == true ? widget.errorMessage : null,border: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(twentyFour)),enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(twentyFour)),borderSide: BorderSide(width: two,color: darkPrimaryColor),focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(twentyFour)),borderSide: BorderSide(
              width: two,color: rosePrimaryColor,);
  }
}

我的按钮组件:

import 'package:covid_app/core/constants/colors.dart';
import 'package:covid_app/core/constants/dimens.dart';
import 'package:Flutter/material.dart';

// ignore: must_be_immutable
class ButtonComponent extends StatefulWidget {
  var title;
  var fillColor;
  var textColor;
  Function loginFun;
  ButtonComponent({Key key,this.title,this.fillColor,this.textColor,this.loginFun});

  @override
  _ButtonComponentState createState() => _ButtonComponentState();
}

class _ButtonComponentState extends State<ButtonComponent> {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: hundredSeventyTwo,height: fortyFour,child: RaisedButton(
        disabledColor: Colors.grey,shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(
            twentyFour,onpressed: widget.loginFun,color: widget.fillColor,child: Text(
          widget.title,style: TextStyle(
            color: widget.textColor,);
  }
}

打印错误https://i.stack.imgur.com/UmQd5.png / https://i.stack.imgur.com/K13rN.png

解决方法

好吧,错误说明了一切,真的没什么可补充的。

formIsValid计算出的内部,您调用2个函数,这些函数可能会修改emailErrorLabelpasswordErrorLabel,并且由于它们既observable且在同一渲染中使用,因此不允许。

computed应该是没有副作用的纯函数,它应该仅从其他computedobservable或常量值中得出一些值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。