0

I'm still relatively new to flutter and even newer to Provider so I may be entirely off with this but from what I've read it looks correct.

General idea is there's a header widget with a button that will either open an endrawer or bring the user to a login page depending on the state of the app.

Login works and the states all are working correctly but only on the login widget. When the user is routed back to the main screen - the state is still in its default state even though the state gets set on a successful login.

The widget tree is like so:
Main
|_ HomeScreen
|     |_ AppHeader
|_ Login


main.dart

  Widget build(BuildContext context) {
    return MultiProvider (
          providers: [
            ChangeNotifierProvider (create: (_) => LoginState(),)
          ],
          child: MaterialApp(
            title: kAppTitle,
            theme: alcDefaultLightTheme(),
            home: HomeScreen(title: "kAppTitle"),
            localizationsDelegates: [
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
              const AlcLocalizationsDelegate(),
            ],
            supportedLocales: [
              const Locale(kEn),
              const Locale(kFr),
            ],
            initialRoute: HomeScreen.id,
            routes: {
              LoadingScreen.id: (context) => LoadingScreen(),
              HomeScreen.id: (context) => HomeScreen(title: kAppTitle),
            }),
    );
  }


home_screen.dart


class HomeScreen extends StatefulWidget {
  static const String id = 'home_screen';

  HomeScreen({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  AccountDrawerOpen() {
    _scaffoldKey.currentState.openEndDrawer();
    FirebaseAnalytics().logEvent(
      name: 'account_drawer_open',
    );
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      ...display code here
      body: AppHeader()
    );}
}


And this is where I need to access the state to determine if the player is logged in or not
app_header.dart

import 'package:provider/provider.dart';

class AppHeader extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    LoginState testLoginState = Provider.of<LoginState>(context);

    return Column(
      children: <Widget>[
        FlatButton(
          child: Text('Check state'),
          onPressed: () {
            print("APP HEADER | STATE IS NOW ${testLoginState.status}");
          },
        )
      ],
    );
  }
}

Lastly, here's my LoginState.dart

enum Status {
  Authenticated,
  Authenticating,
  Unauthenticated,
  InvalidLogin
}

class LoginState with ChangeNotifier {
  Status _status = Status.Unauthenticated;

  Status get status => _status;

  Future signIn(String email, String password) async {
    try {
      _status = Status.Authenticating;
      notifyListeners();

      ... goes to the DB, some logic happens and returns true

      _status = Status.Authenticated;
      notifyListeners();
      print("FROM LOGIN STATE: $_status");

    } catch (e) {
      print('Oops');
      _status = Status.InvalidLogin;
      notifyListeners();
    }
  }

Any help is appreciated, thanks for your help.

Nate
  • 333
  • 3
  • 15

1 Answers1

0

Figured it out. In my Login widget - I had a ChangeNotifierProvider which changes the context. So in this case - this changed the context to the lowest possible widget - the login widget.

Nate
  • 333
  • 3
  • 15
  • Ok, so what was your solution? – PeakGen Sep 30 '20 at 18:25
  • The ChangeNotifierProvider was too low in the tree. The context I was trying to listen to wasn't bubbling up high enough in the tree so I moved the change notifier to be at the root of the app so anything can listen and use the login states. – Nate Oct 01 '20 at 19:53