string - 如何在本地保存用户名并在每个页面 flutter 中显示

我试图在我制作的 flutter 应用程序的每个页面中添加一个用户名。我的意思是在我页面的侧抽屉中我是新手,所以我在这方面遇到了很大的困难帮助我

我尝试使用共享首选项,但我不能这样做,因为变量说它是一个 future 的字符串。我让它在一个人登录时保存用户名,当我试图找回它时它工作我不能

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

我把它加到抽屉里了

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 中无效。帮帮我

最佳答案

SharedPreferences 非常适合存储数据,但正如您所见,它不适合在任何地方使用 - 主要问题是它需要异步加载。您可以在应用程序开始运行时简单地获取它,然后将它传递到您需要它的任何地方,但这并不是特别理想。

我在我的应用程序中所做的,感觉有点像作弊,但到目前为止效果很好,就是将 SharedPreferences 包装到 ScopedModel package 中的模型中。 .

这让我可以编写一些非常方便的包装器。由于从作用域模型中获取数据是同步的,因此使用 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 ...
  }
)

https://stackoverflow.com/questions/56660462/

相关文章:

flutter - Hummingbird(现在是 Flutter for web)计划发布。我应该

dart - ListView.builder 在 flutter 中逐项滚动

dart - Flutter - 创建值和名称数组

dart - 如何在继续 flutter 之前等待 future 的对象?

flutter - 使用 FadeInImage Flutter 正确拟合图像

firebase - 持久化用户身份验证 Flutter Firebase

listview - ListView中如何维护widget的状态?

android-studio - Flutter Emulator 连接到服务协议(protocol

dart - Flutter - 关闭小部件时 BLoC 流实例会导致内存泄漏吗?

dart - 如何在 Flutter 中清除 AnimatedList 中的所有项目