1

What am I mistaking with provider architecture?

My EntryPoint:

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider<AuthProvider>(
            create: (context) => AuthProvider()),
        ChangeNotifierProvider<UserProvider>(
            create: (context) => UserProvider()),
      ],
      child: BdopsApp(),
    ),
  );
}

class BdopsApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.teal,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      initialRoute: LoginView.routeName,
      routes: {
        HomepageView.routeName: (context) => HomepageView(),
        LoginView.routeName: (context) => LoginView(),
      },
    );
  }
}

First I have logged in with my log in credentials.

class LoginView extends StatelessWidget {
  static const routeName = 'LoginView';

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  final User _user = User();

  @override
  Widget build(BuildContext context) {
    return Consumer<AuthProvider>(
      builder: (_, data, __) => Scaffold(
        appBar: CustomAppBar.getAppBar(
          title: 'BDOPS',
          subTitle: 'LOG IN',
        ),
        drawer: SidveNavDrawer(),
        body: Form(
          key: _formKey,
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 20.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                FormInputTextBox(
                  labelText: 'Email',
                  hintText: 'example@domain.com',
                  validator: (value) {
                    if (value == null) {
                      return 'Login email not provided';
                    }
                    if (!RegExp(xEmailRegx).hasMatch(value)) {
                      return 'Not a valid email address';
                    }
                  },
                  onSaved: (value) {
                    _user.email = value.trim();
                  },
                ),
                FormInputTextBox(
                  labelText: 'Password',
                  hintText: '* * * * *',
                  isPassword: true,
                  validator: (value) {
                    if (value == null) {
                      return 'Login password not provided';
                    }
                    if (value.toString().length < 6) {
                      return 'Minmum length is six charector';
                    }
                  },
                  onSaved: (value) {
                    _user.password = value.trim();
                  },
                ),
                Divider(
                  height: 30.0,
                ),
                RaisedButton(
                  color: Colors.deepOrange,
                  padding: EdgeInsets.symmetric(vertical: 10.0),
                  onPressed: () async {
                    if (!_formKey.currentState.validate()) {
                      return;
                    }

                    _formKey.currentState.save();
                    var res = await data.loginUser(_user);

                    if (res == true) {
                      AlertDialog(
                        title: Text('Login Success'),
                      );
                    } else {
                      AlertDialog(
                        title: Text('Login Failed'),
                      );
                    }
                    Navigator.pushReplacementNamed(
                        context, HomepageView.routeName);
                  },
                  child: Text(
                    'SUBMIT',
                    style: xHeaderText,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Than I navigated to the home page where on page load the screen should grab Auth user from AuthUser Provider's getAuthUser and self trigger a method to fetch logged in user's detail from the API with the userID.

class HomepageView extends StatelessWidget {
  static const routeName = 'HomePageView';

  @override
  Widget build(BuildContext context) {
    final userId = Provider.of<AuthProvider>(context).getAuthUser.id;

    return Consumer<UserProvider>(
      builder: (_, dataProvider, __) {
        dataProvider.fetchAUser(userId);
        return Scaffold(
          appBar: CustomAppBar.getAppBar(title: 'BDOPS', subTitle: 'Home'),
          drawer: SidveNavDrawer(),
          body: Text(dataProvider.getSingelUser.email),
        );
      },
    );
  }
}

Doing this, my app at first throws an error and than keeps rebuilding and calling the API over and over again.

enter image description here

enter image description here

My Provider Classes Are:


class AuthProvider with ChangeNotifier {
  User _authUser;
  String _errorMessage;
  AuthTokens _tokens;

  Future<bool> loginUser(User user) async {
    if (user.email == null || user.password == null) {
      _setErrorMessage('Provide login credentials');
    }
    var resp = await APIService().loginUser(
      email: user.email,
      password: user.password,
    );
    if (resp.statusCode == 200) {
      _setAuthToken(authTokensFromJson(resp.body));
      var userFetched =
          await UserProvider().fetchAUser(decodeJwt(_tokens.access)['user_id']);
      if (userFetched != null) {
        _setAuthUser(userFetched);
        return true;
      }
    }
    _setErrorMessage('Failed to login');
    return false;
  }

  void _setAuthToken(value) {
    _tokens = value;
  }

  void _setAuthUser(value) {
    _authUser = value;
    notifyListeners();
  }

  User get getAuthUser {
    return _authUser;
  }

  void _setErrorMessage(value) {
    _errorMessage = value;
    notifyListeners();
  }

  String get getErrorMessage {
    return _errorMessage;
  }
}
class UserProvider with ChangeNotifier {
  User _user;

  Future<User> fetchAUser(userId) async {
    var response = await APIService().getAUser(userId: userId);
    if (response.statusCode == 200) {
      setUser(userFromJson(response.body));

      print('Called from UserProvider');

      return _user;
    }
    return null;
  }

  void setUser(value) {
    _user = value;
    notifyListeners();
  }

  User get getSingelUser {
    return _user;
  }
}
Fahad Md Kamal
  • 243
  • 6
  • 20

0 Answers0