doms
doms

Reputation: 77

Understanding ScopedModel and states in flutter

I hope someone can help me understand ScopedModel in flutter

I have a simple project where when I change a models value, a page wrapper will redirect me to some other page.

In this sample code below, all I want is when I tap login button in the login page, I want the pageWrapper to redirect me to HomePage().

I do notice that after clicking the login button and then I click on the hot reload, I get redirected to the HomePage. which tells me that the model has been updated. Its just that the PageWrapper did not redraw. If thats the case, what should I do so the PageWrapper will redraw when a change has occurred?

Here is a sample code main.dart

void main() => runApp(MyApp(
  model: UserInfoModel(),
));

class MyApp extends StatelessWidget {
  final UserInfoModel model;

  const MyApp({Key key, @required this.model}): super(key: key);


  @override
  Widget build(BuildContext context) {

    return ScopedModel<UserInfoModel>(
      model: model,
      child: MaterialApp(
        title: 'scoped model demo',
        home: PageWrapper(),
      ),
    );
  }
}

page_wrapper.dart

class PageWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<UserInfoModel>(
      builder: (context, child, userInfo){
        if (userInfo.isLoggedIn){
          return Home();
        }else{
          return Login();
        }
      }
    );
  }
}

login.dart

class Login extends StatefulWidget {
  @override
  _LoginState createState() => _LoginState();
}

class _LoginState extends State<Login> {

  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<UserInfoModel>(
      builder: (context, child, userInfoModel){

        return Scaffold(
          appBar: AppBar(
            title: Text("Login"),
          ),
          body: Container(
            child: Center(
                child: FlatButton.icon(onPressed: (){
                  userInfoModel.isLoggedIn=true;
                }, icon: Icon(Icons.person,size: 120,), 
                    label: Text("Login"))
            ),
          ),
        );
      });
  }
}

home.dart

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home"),
      ),
      body: Container(
        child: Center(
          child: Text("you're home"),
        ),
      ),
    );
  }
}

user_info_model.dart

class UserInfoModel extends Model{
  String firstName;
  String lastName;
  bool isLoggedIn=false;

  UserInfoModel({
    this.firstName,
    this.lastName
});

}

Upvotes: 0

Views: 37

Answers (1)

chunhunghan
chunhunghan

Reputation: 54397

You can copy paste run full code below
Step 1: You can interact UserInfoModel with get and set , you can see code below
Step 2: You need notifyListeners()

code snippet

if (userInfo.isLoggedIn) {
            return Home();
...
onPressed: () {
                userInfoModel.isLoggedIn = true;
              },

class UserInfoModel extends Model {
      String firstName;
      String lastName;
      bool _isLoggedIn = false;

      UserInfoModel({this.firstName, this.lastName});

      bool get isLoggedIn => _isLoggedIn;

      set isLoggedIn(bool newSetting) {
        _isLoggedIn = newSetting;
        notifyListeners();
      }
    }                               

working demo

enter image description here

full code

import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';

void main() => runApp(MyApp(
      model: UserInfoModel(),
    ));

class MyApp extends StatelessWidget {
  final UserInfoModel model;

  const MyApp({Key key, @required this.model}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ScopedModel<UserInfoModel>(
      model: model,
      child: MaterialApp(
        title: 'scoped model demo',
        home: PageWrapper(),
      ),
    );
  }
}

class PageWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<UserInfoModel>(
        builder: (context, child, userInfo) {
      if (userInfo.isLoggedIn) {
        return Home();
      } else {
        return Login();
      }
    });
  }
}

class Login extends StatefulWidget {
  @override
  _LoginState createState() => _LoginState();
}

class _LoginState extends State<Login> {
  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<UserInfoModel>(
        builder: (context, child, userInfoModel) {
      return Scaffold(
        appBar: AppBar(
          title: Text("Login"),
        ),
        body: Container(
          child: Center(
              child: FlatButton.icon(
                  onPressed: () {
                    userInfoModel.isLoggedIn = true;
                  },
                  icon: Icon(
                    Icons.person,
                    size: 120,
                  ),
                  label: Text("Login"))),
        ),
      );
    });
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home"),
      ),
      body: Container(
        child: Center(
          child: Text("you're home"),
        ),
      ),
    );
  }
}

class UserInfoModel extends Model {
  String firstName;
  String lastName;
  bool _isLoggedIn = false;

  UserInfoModel({this.firstName, this.lastName});

  bool get isLoggedIn => _isLoggedIn;

  set isLoggedIn(bool newSetting) {
    _isLoggedIn = newSetting;
    notifyListeners();
  }
}

Upvotes: 1

Related Questions