首页 > 解决方案 > Flutter firebase 登录导致 NoSuchMethodError

问题描述

我正在按照教程使用 firebase 在颤振中创建身份验证系统。注册按预期工作,并且用户已发布到我的 firebase 数据库,但是,当我尝试使用正确的凭据登录时,我得到:

I/flutter (26424): user A a@a.com added
I/InputMethodManager(26424): showSoftInput
I/InputMethodManager(26424): mServedView =com.waifuhub.app;view =com.waifuhub.app;flags =0
I/HwSecImmHelper(26424): mSecurityInputMethodService is null
W/InputMethodManager(26424): startInputReason = 3
W/IInputConnectionWrapper(26424): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper(26424): getSelectedText on inactive InputConnection
W/IInputConnectionWrapper(26424): getTextAfterCursor on inactive InputConnection
W/IInputConnectionWrapper(26424): requestCursorAnchorInfo on inactive InputConnection
I/InputMethodManager(26424): showSoftInput
I/InputMethodManager(26424): mServedView =com.waifuhub.app;view =com.waifuhub.app;flags =0
I/HwSecImmHelper(26424): mSecurityInputMethodService is null
W/InputMethodManager(26424): startInputReason = 3
V/AudioManager(26424): playSoundEffect   effectType: 0
V/AudioManager(26424): querySoundEffectsEnabled...
I/HwSecImmHelper(26424): mSecurityInputMethodService is null
I/ViewRootImpl(26424): jank_removeInvalidNode all the node in jank list is out of time
I/flutter (26424): Sign In Error: NoSuchMethodError: The getter 'data' was called on null.
I/flutter (26424): Receiver: null
I/flutter (26424): Tried calling: data
Application finished.
Exited (sigterm)

负责登录的代码如下:

void _emailLogin(
      {String email, String password, BuildContext context}) async {
    if (_formKey.currentState.validate()) {
      try {
        SystemChannels.textInput.invokeMethod('TextInput.hide');
        await _changeLoadingVisible();
        //need await so it has chance to go through error if found.
        await StateWidget.of(context).logInUser(email, password);
        await Navigator.pushNamed(context, '/');
      } catch (e) {
        _changeLoadingVisible();
        print("Sign In Error: $e");
        String exception = Auth.getExceptionText(e);
        Flushbar(
          title: "Sign In Error",
          message: exception,
          duration: Duration(seconds: 5),
        )..show(context);
      }
    } else {
      setState(() => _autoValidate = true);
    }
  }
class StateWidget extends StatefulWidget {
  final StateModel state;
  final Widget child;

  StateWidget({
    @required this.child,
    this.state,
  });

  // Returns data of the nearest widget _StateDataWidget
  // in the widget tree.
  static _StateWidgetState of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<_StateDataWidget>().data;
  }

  @override
  _StateWidgetState createState() => new _StateWidgetState();
}

class _StateWidgetState extends State<StateWidget> {
  StateModel state;
  //GoogleSignInAccount googleAccount;
  //final GoogleSignIn googleSignIn = new GoogleSignIn();

  @override
  void initState() {
    super.initState();
    if (widget.state != null) {
      state = widget.state;
    } else {
      state = new StateModel(isLoading: true);
      initUser();
    }
  }

  Future<Null> initUser() async {
    //print('...initUser...');
    FirebaseUser firebaseUserAuth = await Auth.getCurrentFirebaseUser();
    User user = await Auth.getUserLocal();
    Settings settings = await Auth.getSettingsLocal();
    setState(() {
      state.isLoading = false;
      state.firebaseUserAuth = firebaseUserAuth;
      state.user = user;
      state.settings = settings;
    });
  }

  Future<void> logOutUser() async {
    await Auth.signOut();
    FirebaseUser firebaseUserAuth = await Auth.getCurrentFirebaseUser();
    setState(() {
      state.user = null;
      state.settings = null;
      state.firebaseUserAuth = firebaseUserAuth;
    });
  }

  Future<void> logInUser(email, password) async {
    String userId = await Auth.signIn(email, password);
    User user = await Auth.getUserFirestore(userId);
    await Auth.storeUserLocal(user);
    Settings settings = await Auth.getSettingsFirestore(userId);
    await Auth.storeSettingsLocal(settings);
    await initUser();
  }

  @override
  Widget build(BuildContext context) {
    return new _StateDataWidget(
      data: this,
      child: widget.child,
    );
  }
}

class _StateDataWidget extends InheritedWidget {
  final _StateWidgetState data;

  _StateDataWidget({
    Key key,
    @required Widget child,
    @required this.data,
  }) : super(key: key, child: child);

  // Rebuild the widgets that inherit from this widget
  // on every rebuild of _StateDataWidget:
  @override
  bool updateShouldNotify(_StateDataWidget old) => true;
}
static Future<String> signIn(String email, String password) async {
    FirebaseUser user = (await FirebaseAuth.instance
            .signInWithEmailAndPassword(email: email, password: password))
        .user;
    return user.uid;
  }
class Validator {
  static String validateEmail(String value) {
    Pattern pattern = r'^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+';
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value))
      return 'Please enter a valid email address.';
    else
      return null;
  }

  static String validatePassword(String value) {
    Pattern pattern = r'^.{6,}$';
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value))
      return 'Password must be at least 6 characters.';
    else
      return null;
  }

  static String validateName(String value) {
    Pattern pattern = r"^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$";
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value))
      return 'Please enter a name.';
    else
      return null;
  }

  static String validateNumber(String value) {
    Pattern pattern = r'^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$';
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value))
      return 'Please enter a number.';
    else
      return null;
  }
}

我的依赖项pubsec.yaml

dependencies:
  flutter:
    sdk: flutter
  flutter_launcher_icons: ^0.7.2
  cupertino_icons: ^0.1.2
  firebase_auth: ^0.15.5+3
  cloud_firestore: ^0.13.4+2
  flushbar: 1.9.1
  shared_preferences: ^0.5.6+3

dev_dependencies:
  flutter_test:
    sdk: flutter

在进一步调试后,我认为错误是由于 null 上下文被传递给的事实 _StateWidgetState,但是,我不确定是否是这样,或者如何解决这个问题。任何帮助将不胜感激!

标签: firebaseflutterdartfirebase-authentication

解决方案


不确定,但您似乎错过了电话

_formKey.currentState.save();

打电话后_formKey.currentState.validate()

否则,此行会导致错误:

static _StateWidgetState of(BuildContext context) {
    return (context.dependOnInheritedWidgetOfExactType() as _StateDataWidget)
        .data;
  }

(context.dependOnInheritedWidgetOfExactType() as _StateDataWidget)是返回 null

将其更改为:

return (context.inheritFromWidgetOfExactType(_StateDataWidget) as _StateDataWidget).data;

或者

return context.dependOnInheritedWidgetOfExactType<_StateDataWidget>().data;

推荐阅读