How to save a username locally and display it in every page flutter

2,310

Solution 1

Why don't you use Secure Storage Plugin?

// Create storage
final storage = new FlutterSecureStorage();

// Read value 
String value = await storage.read(key: key);

// Read all values
Map<String, String> allValues = await storage.readAll();

// Delete value 
await storage.delete(key: key);

// Delete all 
await storage.deleteAll();

// Write value 
await storage.write(key: key, value: value);

Solution 2

SharedPreferences is good for storing data, but as you have seen it isn't great for using everywhere - the main issue being that it needs to be loaded asynchronously. You could simply get it when the application starts running and then pass it around everywhere you need it, but that isn't particularly ideal.

What I've done in my application, which feels a little bit like cheating but has worked very well so far, is to wrap the SharedPreferences into a Model from the ScopedModel package.

This allows me to write some very convenient wrappers. And since getting data out of the scoped model is synchronous, it makes using SharePreferences pretty easy.

That looks like this:

abstract class _PreferenceKeys {
  static const USERNAME = 'username';
}

class PreferenceModel extends Model {
  static PreferenceModel of(BuildContext context, {bool rebuildOnChange = false}) => ScopedModel.of<PreferenceModel>(context, rebuildOnChange: rebuildOnChange);


  final SharedPreferences sharedPreferences;

  PreferenceModel(this.sharedPreferences);

  // Helpers to set in values which ensure that notifyListeners gets called
  Future<bool> _setString(String key, String value, {bool notify = true}) async {
    final val = await sharedPreferences.setString(key, value);
    if (notify) notifyListeners();
    return val;
  }
  Future<bool> _setBool(String key, bool value, {bool notify = true}) async {
    final fut = await sharedPreferences.setBool(key, value);
    if (notify) notifyListeners();
    return fut;
  }

  String get username => sharedPreferences.getString(_PreferenceKeys.USERNAME);

  void set username(String username) => _setString(_PreferenceKeys.USERNAME, userName);

The biggest downside to this approach is that any errors in the _setString method don't get propagated back out - you could use Future functions for setting the username if that's an issue you'd like to deal with, or do something in _setString to handle it. I personally haven't had any problems though.

There's one more trick that goes with this. You can make the main function of your application asynchronous, which means that you can do this:

main() async {
  final sharedPreferences = await SharedPreferences.getInstance();

  runApp(
    ScopedModel<PreferenceModel>(
      model: PreferenceModel(sharedPreferences),
      child: ...
    ),
  )
}

And then to use this in your code, you can simply use:

PreferenceModel.of(context).userName

 or

PreferenceModel.of(context, rebuildOnChange: true).userName

or

child: ScopedModelDescendant<PreferenceModel>(
  child: ...
  builder: (context, model, child) {
    // do whatever with model
    return ...
  }
)

Solution 3

If you want to do it exactly your way - you can wrap Text inside FutureBuilder

Future<String> _get() async {
    final prefs = await SharedPreferences.getInstance();
    final name = "username";
    var username = prefs.getString(name);
    return username;
  }

ListTile(
  title: FutureBuilder(builder: (context, snapshot) {
    if (snapshot.hasData) return Text(snapshot.data);
    else return Text('');
  }, future: _get(),),.....),

UPD:

For saving name in variable

String name = '';

@override
void initState() {
  super.initState();
  _get().then((value) {
    setState(() {
      name = value;
    });
  });
}

Solution 4

What you can do is In initstate you get the data and use "then" keyword assign a username to variable and use the variable across your storage and also build your app inside "then". It waits until you get the data and then build your app

Share:
2,310
Admin
Author by

Admin

Updated on December 12, 2022

Comments

  • Admin
    Admin over 1 year

    Im trying to add a username in every pages of a flutter application i made. i mean in the sidedrawers of my page Im new to flutter so im facing very difficulty in this help me

    I tried using shared preferences but i cant do it as the the variable says as it is a future string. i made it to save the username when a person login and it works when i tried to gain it back i cant

      Future<String> getuname() async {
        final prefs = await SharedPreferences.getInstance();
        final name = "username";
        var user = prefs.getString(name);
        var username = '${user[0].toUpperCase()}${user.substring(1)}';
        print('get $username');
        return username;
      }
    

    and i added this to sidedrawer

    ListTile(
                  leading: Icon(Icons.user),
                  title: Text(_get()),
                  onTap: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(builder: (context) => MyProfilePage()),
                    );
                  }),
    
      String uname = '';
      @override
      void initState() {
    
        getuname().then((value) {
        setState(() {
          uname = value;
        });
      });
        _selectedDay = DateTime.now();
        _events = {
          _selectedDay.subtract(Duration(days: 30)): ['Event A0', 'Event B0', 'Event C0'],
          _selectedDay.subtract(Duration(days: 27)): ['Event A1'],
          _selectedDay.subtract(Duration(days: 20)): ['Event A2', 'Event B2', 'Event C2', 'Event D2'],
          _selectedDay.subtract(Duration(days: 16)): ['Event A3', 'Event B3'],
          _selectedDay.subtract(Duration(days: 10)): ['Event A4', 'Event B4', 'Event C4'],
          _selectedDay.subtract(Duration(days: 4)): ['Event A5', 'Event B5', 'Event C5'],
          _selectedDay.subtract(Duration(days: 2)): ['Event A6', 'Event B6'],
          _selectedDay: [uname, 'Event B7', 'Event C7', 'Event D7'],
          _selectedDay.add(Duration(days: 1)): ['Event A8v', 'Event B8', 'Event C8', 'Event D8'],
          _selectedDay.add(Duration(days: 3)): Set.from(['Event A9', 'Event A9', 'Event B9']).toList(),
          _selectedDay.add(Duration(days: 7)): ['Event A10', 'Event B10', 'Event C10'],
          _selectedDay.add(Duration(days: 11)): ['Event A11', 'Event B11'],
          _selectedDay.add(Duration(days: 17)): ['Event A12', 'Event B12', 'Event C12', 'Event D12'],
          _selectedDay.add(Duration(days: 22)): ['Event A13', 'Event B13'],
          _selectedDay.add(Duration(days: 26)): ['Event A14', 'Event B14', 'Event C14'],
        };
    
        _selectedEvents = _events[_selectedDay] ?? [];
        _visibleEvents = _events;
        _visibleHolidays = _holidays;
    
        _controller = AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 400),
        );
    
        _controller.forward();
    
        super.initState();
      }
    

    I cant get the value of username, but it works in widget but not inside the initstate. help me