Apol
Apol

Reputation: 29

Flutter firebase logging in causes NoSuchMethodError

I was following a tutorial to create an authentication system in flutter using firebase. Registration works as intended and the user is posted to my firebase database, however, when I try to login with the correct credentials, I get:

I/flutter (26424): user A [email protected] 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)

The code responsible for signing in is as follows:

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;
  }
}

And my dependencies in 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

Upon further debugging, I think the error is due to the fact that null context is being passed to _StateWidgetState, however, I am not sure if this is so, or how to solve this. Any help would be highly appreciated!

Upvotes: 0

Views: 445

Answers (1)

aldobaie
aldobaie

Reputation: 1407

Not sure, but it seems you're missing calling

_formKey.currentState.save();

after calling _formKey.currentState.validate().

Otherwise this line is causing the error:

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

This (context.dependOnInheritedWidgetOfExactType() as _StateDataWidget) is returning null

change it to:

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

or

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

Upvotes: 1

Related Questions