1

I have a problem make me annoying about the drawer. I have Drawer inside FutureBuilder for fetching user profiles from API. The problem is every I swipe/open the drawer, it will refresh before fetching the user profile. It makes a bad user experience.

I already searching how to make FutureBuilder run once only from this , But the drawer still refreshes.

I missed something?

Drawer Custom

class _DrysDrawerCustomState extends State<DrysDrawerCustom> {
  Future<List<UserModel>> userList;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final username = Provider.of<GlobalProvider>(context).username;
    userList = userApi.getUserByUsername(username: username);
  }

  @override
  Widget build(BuildContext context) {
    final globalProvider = Provider.of<GlobalProvider>(context, listen: false);
    //TODO Change Structure Drawer
    return FutureBuilder(
      future: userList,
      builder: (BuildContext context, AsyncSnapshot<List<UserModel>> snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasError) {
            return ErrorFutureBuilder(errorText: snapshot.error);
          } else {
            final user = snapshot.data[0];
            return DrawerCustom(
              imageUrl: "${userApi.baseImageUrl}/${user.fotoUser}",
              detailUser: [
                Text(user.namaUser),
                Text(user.namaGroup),
              ],
              drawerMenu: [
                DrawerMenu(
                  menuName: "Profil Info",
                  icon: Icons.people_outline,
                  onTap: () => Navigator.of(context)
                      .pushNamed(ProfilInfoScreen.routeNamed),
                ),
                DrawerMenu(
                  menuName: "Ganti Password",
                  icon: Icons.lock,
                  onTap: () => Navigator.of(context)
                      .pushNamed(ChangePasswordScreen.routeNamed),
                ),
                Divider(),
                DrawerMenu(
                  menuName: "Logout",
                  icon: Icons.arrow_back,
                  onTap: () {
                    globalProvider.removeUsername();
                    Navigator.of(context)
                        .pushReplacementNamed(LoginScreen.routeNamed);
                  },
                ),
              ],
            );
          }
        } else {
          return LoadingFutureBuilder();
        }
      },
    );
  }
}

Global Provider

GlobalProvider() {
    _initialSharedPreferences();
  }
String _username;
  String get username => _username;

  void _initialSharedPreferences() async {
    await getUsername();
  }

  Future updateUsername(String username) async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    await pref.setString("username", username);
    //! It's Important !!! After update / remove sharedpreferences  , must called getUsername() to updated the value.
    await getUsername();
    notifyListeners();
  }

  Future removeUsername() async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    final result = await pref.remove("username");
    //! It's Important !!! After update / remove sharedpreferences  , must called getUsername() to updated the value.
    await getUsername();
    notifyListeners();
    return result;
  }

  Future getUsername() async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    final result = pref.getString("username");
    _username = result;
    notifyListeners();
  }
Hamed
  • 5,867
  • 4
  • 32
  • 56
Zeffry Reynando
  • 3,445
  • 12
  • 49
  • 89

1 Answers1

0

Make "user" a global variable and inside build check if user is null, then return FutureBuilder(...) as you've done; Otherwise, just return the DrawerCustom(...) immediately. Hope this answers your question.

if(user == null)
  return FutureBuilder(...) // don't forget to set user as you've done already
else
  return DrawerCustom(...)
aldobaie
  • 1,387
  • 10
  • 15