FilledStacks / flutter-tutorials

The repo contains the source code for all the tutorials on the FilledStacks Youtube channel.
MIT License
4.74k stars 1.76k forks source link

Shared model #146

Open stoppimyse opened 2 years ago

stoppimyse commented 2 years ago

Hi, I have a question, I have this code:

StartUpScreen:

class StartUpScreen extends StatelessWidget {
  const StartUpScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var userProvider = context.read<UserProvider>();
    return ViewModelBuilder<StartUpViewModel>.reactive(
      viewModelBuilder: () => StartUpViewModel(),
      onModelReady: (model) => model.handleStartUpLogic(),
      builder: (context, model, child) => Scaffold(
          backgroundColor: Colors.white,
          body: model.isBusy
              ? const CircularProgressIndicator()
              : model.isLogged
                  ? const HomeScreen()
                  : LoginScreen()),
    );
  }
}

and relative view model:

class StartUpViewModel extends BaseViewModel {
  final AuthenticationService _authenticationService = locator<AuthenticationService>();

  bool _isLogged = false;
  bool get isLogged {
    return _isLogged;
  }

  Future handleStartUpLogic() async {
    setBusy(true);
    bool hasLoggedInUser = _authenticationService.isUserLoggedIn();
    if (hasLoggedInUser) {
      _isLogged = true;
      setBusy(false);
    } else {
      _isLogged = false;
      setBusy(false);
    }
  }
}

on lunch application I'm not logged and the app show me LoginScreen:

class LoginScreen extends StatelessWidget {
  LoginScreen({Key? key}) : super(key: key);

  final emailController = TextEditingController();
  final passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return ViewModelBuilder<LoginViewModel>.reactive(
      viewModelBuilder: () => LoginViewModel(),
      builder: (context, model, child) => Scaffold(
        backgroundColor: Colors.white,
        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 50),
          child: Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              SizedBox(
                height: 150,
                child: Image.asset('assets/images/title.png'),
              ),
              InputField(
                placeholder: 'Email',
                controller: emailController,
              ),
              verticalSpaceSmall,
              InputField(
                placeholder: 'Password',
                password: true,
                controller: passwordController,
              ),
              verticalSpaceMedium,
              Row(
                mainAxisSize: MainAxisSize.max,
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  BusyButton(
                    title: 'Login',
                    busy: model.isBusy,
                    onPressed: () {
                      model.login(
                        email: emailController.text,
                        password: passwordController.text,
                      );
                    },
                  )
                ],
              ),
              verticalSpaceMedium,
            ],
          ),
        ),
      ),
    );
  }
}

and relative view model:

class LoginViewModel extends BaseViewModel {
  final AuthenticationService _authenticationService = locator<AuthenticationService>();
  final DialogService _dialogService = locator<DialogService>();

  Future<void> login({
    required String email,
    required String password,
  }) async {
    try {
      setBusy(true);
      await _authenticationService.loginWithEmail(
        email: "myemail",
        password: "mypass!",
      );
      setBusy(false);
    } catch (e) {
      setBusy(false);
      await _dialogService.showDialog(
        title: 'Login Failure',
        description: 'General login failure. Please try again later',
      );
    }
  }
}

The question is, how to change model.isLogged on StartUpViewModel for reload the widget and show the LoginScreen simil to classic provider? I could use navigation but this operation can be useful for other pages as well. for example, in classic provider i've a Page A with total coins, in Page B i add 10 coin, with provider i can update the value with notifyListeners(); without call the server. How to emulate this? it's possible?