Как сохранить имя пользователя локально и отображать его на каждой странице - PullRequest
4 голосов
/ 19 июня 2019

Я пытаюсь добавить имя пользователя на каждой странице созданного мною приложения.Я имею в виду, что в боковых окнах моей страницы я новичок во флаттере, поэтому мне очень трудно в этом помочь.

Я пытался использовать общие настройки, но я не могу сделать это, поскольку переменная говорит, что это будущая строка.я сделал это, чтобы сохранить имя пользователя при входе пользователя, и оно работает, когда я пытался получить его обратно, я не могу

  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;
  }

, и я добавил это в 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();
  }

Я не могу получить значение имени пользователя, но оно работает в виджете, но не внутри initstate.помоги мне

Ответы [ 3 ]

2 голосов
/ 19 июня 2019

Если вы хотите сделать это по-своему - вы можете обернуть Text внутрь 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:

Для сохранения имени в переменной

String name = '';

@override
void initState() {
  super.initState();
  _get().then((value) {
    setState(() {
      name = value;
    });
  });
}
2 голосов
/ 19 июня 2019

SharedPreferences хорош для хранения данных, но, как вы видели, он не подходит для повсеместного использования - основная проблема заключается в том, что его нужно загружать асинхронно. Вы можете просто получить его, когда приложение начнет работать, и затем передавать его везде, где вам это нужно, но это не особенно идеально.

То, что я сделал в своем приложении, которое немного похоже на читерство, но до сих пор работало очень хорошо, - это обернул SharedPreferences в модель из пакета ScopedModel .

Это позволяет мне написать несколько очень удобных обёрток. А поскольку синхронное извлечение данных из модели области действия делает использование SharePreferences довольно простым.

Это выглядит так:

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);

Самым большим недостатком этого подхода является то, что любые ошибки в методе _setString не распространяются обратно - вы можете использовать функции Future для установки имени пользователя, если вы хотите решить эту проблему, или сделать что-то в _setString, чтобы справиться с этим. Лично у меня не было никаких проблем.

Есть еще одна хитрость, которая связана с этим. Вы можете сделать основную функцию вашего приложения асинхронной, что означает, что вы можете сделать это:

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

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

И затем, чтобы использовать это в своем коде, вы можете просто использовать:

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 ...
  }
)
1 голос
/ 19 июня 2019

Что вы можете сделать, так это в initstate получить данные и использовать ключевое слово «then», присвоить имя переменной переменной и использовать переменную в вашем хранилище, а также создать приложение внутри «then». Он ждет, пока вы получите данные и затем создадите ваше приложение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...