0

im trying to build an app which consists of 3 roles, student teacher and parent. I thought of implementing the authentication using auth change stream and shared preferences. ie setInt('usertype',1) for student, 2 for teacher and 3 for parent.

this is my student registration screen where if the user is successfully registered, im setting the usertype as 1, also i did the same for teacher and parent registration screen.

class StudentRegisterScreen extends StatefulWidget {
  final Function toggleView;
  StudentRegisterScreen({this.toggleView});
  @override
  _StudentRegisterScreenState createState() => _StudentRegisterScreenState();
}

class _StudentRegisterScreenState extends State<StudentRegisterScreen> {
  final AuthService _authService = AuthService();

  final _formkey = GlobalKey<FormState>();
  final usertype = await SharedPreferences.getInstance();
  //String name = '';
  //String email = '';
  //String password = '';
  
  @override
  Widget build(BuildContext context) {
    //String _message = '';
    Size size = MediaQuery.of(context).size;

    return Scaffold(
      backgroundColor: HexColor(studentPrimaryColour),
      body: SafeArea(
        child: SingleChildScrollView(
          child: Form(
            key: _formkey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                SizedBox(
                  height: 20.0,
                ),
                HeadingText(
                  text: 'Register',
                  size: 60.0,
                  color: Colors.white,
                ),
                Container(
                  height: 20.0,
                  child: HeadingText(
                    text: AuthService().message,
                    size: 20.0,
                    color: Colors.white,
                  ),
                ),
                SizedBox(
                  height: 25.0,
                ),
                RoundedInputField(
                  hintText: 'Name',
                  validator: (val) =>
                      val.isEmpty ? 'Oops! you left this field empty' : null,
                  onChanged: (val) {
                    name = val;
                  },
                ),
                SizedBox(
                  height: 5.0,
                ),
               
                RoundedInputField(
                  hintText: 'Email',
                  validator: (val) => val.isEmpty ? 'enter an email' : null,
                  onChanged: (val) {
                    email = val;
                  },
                ),
                SizedBox(
                  height: 5.0,
                ),
                RoundedInputField(
                    hintText: 'Password',
                    validator: (val) =>
                        val.isEmpty ? 'atleast provide a password' : null,
                    boolean: true,
                    onChanged: (val) {
                      password = val;
                    }),
                SizedBox(
                  height: 5.0,
                ),
                Container(
                  margin: EdgeInsets.symmetric(vertical: 10),
                  width: size.width * 0.8,
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(29),
                    child: FlatButton(
                      padding:
                          EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                      color: Colors.white,
                      onPressed: () async {
                        
                        // 
                        //   if (_formkey.currentState.validate()) {
                        //     print(email);
                        //     print(password);
                               usertype.setInt('usertype',1);
                        //     dynamic result =
                        //         await _authService.registerWithEmailpasswd(
                        //             email,
                        //             password,
                        //             name,
                        //            );
                        //    
                      },
                      child: HeadingText(
                        color: HexColor(studentPrimaryColour),
                        text: 'Register',
                        size: 12.0,
                      ),
                    ),
                  ),
                ),
                SizedBox(
                  height: 15.0,
                ),
                InkWell(
                  onTap: () {
                    // Navigator.pop(context);
                    widget.toggleView();
                  },
                  child: HeadingText(
                    text: 'Already registered?',
                    color: Colors.white,
                    size: 10,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}


but im getting an error

I/flutter (13157): 0
E/flutter (13157): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'setInt' was called on null.
E/flutter (13157): Receiver: null
E/flutter (13157): Tried calling: setInt("usertype", 1)


this below is my wrapper class right now, I thought of printing the values on to the console before proceeding further, i will be implementing switch cases for showing the different user screens


class Welcomescreen extends StatefulWidget {
  @override
  _WelcomescreenState createState() => _WelcomescreenState();
}

class _WelcomescreenState extends State<Welcomescreen> {
  SharedPreferences userDetails;
  int usertype;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    checkUserType();
  }

  void checkUserType() async {
    userDetails = await SharedPreferences.getInstance();
    setState(() {
      usertype = userDetails.getInt('usertype') ?? 0;
    });

    print(usertype);
  }

  @override
  Widget build(BuildContext context) {
    //final user = Provider.of<UserModel>(context);
    return Body();
  }
}


  • ```checkUserType``` is ```async``` , it dould be ```Future``` not ```void```, and you must await for ```checkUserType``` to be done, so you have to call it inside instead ```WidgetsBinding.instance.addPostFrameCallback((_) async => await checkUserType());``` since ```initState``` is not ```async``` function – ikerfah Nov 08 '20 at 23:17
  • The answer here [link](https://stackoverflow.com/questions/53363774/importance-of-calling-setstate-inside-initstate), related to calling `setState`inside `initState`, can be helpful – Eduardo Nov 08 '20 at 23:42
  • @ikerfah tried adding `Future` and ```WidgetsBinding.instance.addPostFrameCallback((_) async => await checkUserType()); ``` inside init(), but throws the same error.. ``` E/flutter (14753): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'setInt' was called on null. E/flutter (14753): Receiver: null E/flutter (14753): Tried calling: setInt("usertype", 1)``` – Anugrah_kora Nov 09 '20 at 05:12

1 Answers1

0

userType is referencing a future value SharedPreference.getInstance(), by creating final userType = await SharedPrefence.getInstance() you're telling the code that calling userType will return a Future of SharedPrefence.getInstance(), is not resolving to the SharedPreference class until you actually await for it (using await is not doing anything because you're not really inside an asyn function)

try calling it like this:

onPressed: () async {
    (await usertype).setInt('usertype',1);
     // or maybe (userType).setInt('usertype',1);
}

userType will be replaced for the value you're referencing (await SharedPreference.getInstance())

for the program it looks like this:

onPressed: () async {
    (await SharedPreference.getInstance()).setInt('usertype',1);
}

first it needs to await the furure, after that you can actually call its methods

EdwynZN
  • 4,895
  • 2
  • 12
  • 15