responsive_builder icon indicating copy to clipboard operation
responsive_builder copied to clipboard

ScreenTypeLayout widgets don't rebuild on browser refresh

Open verscph opened this issue 3 years ago • 1 comments

The StartupView of my app checks whether the user is logged in and navigates to "Home" or "LoginView".

When using responsive_builder, the widgets are not rebuilt when the user refreshes the browser.

My code:

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

  @override
  Widget build(BuildContext context) {
    print('StartupView');
    return ScreenTypeLayout(
      breakpoints: ScreenBreakpoints(desktop: 1920, tablet: 900, watch: 375),
      mobile: StartUpViewMobile(),
      tablet: StartUpViewTablet(),
      desktop: StartupViewDesktop()
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    print('StartupViewDesktop');
    return ViewModelBuilder<StartUpViewModel>.reactive(
      viewModelBuilder: () => StartUpViewModel(),
      onModelReady: (model) => model.handleStartUpLogic(),
      builder: (context, model, child) => Scaffold(
        extendBodyBehindAppBar: true,
        extendBody: true,
        body: Center(
          child: CircularProgressIndicator(
            strokeWidth: 3,
            valueColor: AlwaysStoppedAnimation(
              Theme.of(context).accentColor,
            ),
          ),
        ),
      ),
    );
  }
}

class StartUpViewModel extends BaseModel {
  final AuthenticationService _authenticationService =
      locator<AuthenticationService>();
  final NavigationService _navigationService = locator<NavigationService>();

  Future handleStartUpLogic() async {
    bool firstTime = true;
    _authenticationService.authChanges.listen((user) async {
      if (user != null) {
        _navigationService.clearStackAndShow(Routes.homeView);
      }
      if (!firstTime && user == null) {
        if (_authenticationService.platform == 'WEB') {
          _navigationService.clearStackAndShow(Routes.loginView);
        } else {
          _navigationService.clearStackAndShow(Routes.welcomeView);
        }
      }
      firstTime = false;
    });
  }
}

The console output on startup:

StartupView
StartupViewDesktop

When I refresh the browser, the StartupViewDesktop widget isn't rebuilt. The console output is:

StartupView

and it adds the page to the navigation stack which makes the widget Navigator.of(context).canPop() == true

Screenshot 2021-03-21 at 13 07 55

All works as expected when using

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

  @override
  Widget build(BuildContext context) {
    print('StartupView');
    return StartupViewDesktop();
  }
}

then, the StartupViewDesktop is rebuilt on refreshing the browser and Navigator.of(context).canPop() == false

Screenshot 2021-03-21 at 13 15 21

Looks like responsive_builder doesn't handle the widget state appropriately?

Thanks for your help!

verscph avatar Mar 21 '21 12:03 verscph

You can pass in the builders instead using

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

  @override
  Widget build(BuildContext context) {
    print('StartupView');
    return ScreenTypeLayout.builder(
      breakpoints: ScreenBreakpoints(desktop: 1920, tablet: 900, watch: 375),
      mobile: (context) => StartUpViewMobile(),
      tablet: (context) => StartUpViewTablet(),
      desktop: (context) => StartupViewDesktop()
    );
  }
}

That should rebuild on refresh.

FilledStacks avatar Mar 23 '21 15:03 FilledStacks