Exécuter une tâche asynchrone dans le navigateur 2.0

Bonjour à tous,
J’ai un soucis dans le codage de mon application. J’utilise le navigateur 2.0 et tout fonctionnais dans mon application. Seulement maintenant j’essaye de faire l’intégration du stockage des données avec shared preferences. En effet je compte stocker le nom de l’utilisateur. Donc j’ai une page de login pour la première connexion puis une page principal.

Widget build(BuildContext context) {
    final List<Page<dynamic>> pagesList = [];
    String? userName = await UserData.getName();
    if (userName == null) {
      final loginPageScreen = LoginScreen(LoginViewModel(this));
      pagesList.add(MaterialPage(child: loginPageScreen));
    } else {
      final homePageScreen =
          HomeScreen((HomeViewModel(this, _todoManager, this, this)));
      pagesList.add(MaterialPage(child: homePageScreen));
    }
    return Navigator(
      key: navigatorKey,
      pages: pagesList,
      onPopPage: (route, result) {
        if (route.didPop(result) == false) {
          return false;
        }
        return onBackButtonTouched(result);
      },
    );
  }

J’ai un soucis car je suis obligé d’attendre que le nom d’utilisateur soit chargé mais je n’ai pas le droit. Comment faire dans ce cas de figure?

(Toute l’application fonctionnait bien avant l’ajout de shared preferences, et je n’ai mis que la partie du widget build qui me semble importante)

class UserData {
  static void setName(String newName) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString("name", newName);
  }

  static Future<String?> getName() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    return prefs.getString("name");
  }
}

Hello,

J’ai l’impression que tu utilise la valeur de ton userName pour choisir si tu affiche la page login ou ton HomeScreen.

Je peux te suggérer de sortir ta déclaration de userName de ton build.

String? userName;
Widget build(BuildContext context) {
...

Cela te permettra modifier ton userName depuis tes Viewmodel en appelant une méthode de ton routeur depuis ton LoginScreen du genre :

void setUserName(String? userName){
    this.userName = userName;
    notifyListener();
}

Pour initialiser une première fois ton login, tu peux le faire :

  • Depuis ton LoginScreen
  • Depuis le constructeur de ton Navigator.

Dans le LoginScreen

//@override
void initState() {
    super.initState();
    UserData.getName().then((value) {
        _viewmodel.setUserName(value);
    });
}

Dans le constructeur

ton_navigator_constructeur() {
   UserData.getName().then((value) {
        this.userName = value;
        notifyListener();
    });
}

Par contre la page LoginScreen devrait s’afficher le temps de charger le login depuis les SharedPreferences comme sur l’app PurpleGirafe.
Si ça te gène pourquoi pas rajouter une page de chargement pendant que tu récupère la valeur du SharedPreferences ?

Merci beaucoup pour avoir pris le temps de me répondre @isanforc
Je vais effectivement devoir charger une page avant mais mon soucis maintenant c’est que je ne peux pas utiliser la méthode initState car j’utilise des stateLess widgets avec l’architecture du ViewModel. Mais je vais tenter de trouver une solution.