如何在本地保存用户名并在每个页面颤振中显示它
How to save a username locally and display it in every page flutter
我试图在我制作的 Flutter 应用程序的每个页面中添加用户名。我的意思是在我页面的侧边栏中,我是 flutter 的新手,所以我在这方面遇到了很大的困难帮助我
我尝试使用共享首选项,但我不能像变量所说的那样做,因为它是未来的字符串。我让它在一个人登录时保存用户名,当我试图取回它时它起作用了我不能
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 ...
}
)
如果您想按照自己的方式进行 - 您可以将 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(),),.....),
更新:
用于在变量中保存名称
String name = '';
@override
void initState() {
super.initState();
_get().then((value) {
setState(() {
name = value;
});
});
}
您可以做的是在 initstate 中获取数据并使用 "then" 关键字将用户名分配给变量并在整个存储中使用该变量,并在 "then" 中构建您的应用程序。它会等到您获得数据,然后构建您的应用程序
为什么不使用安全存储插件?
// 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);
我试图在我制作的 Flutter 应用程序的每个页面中添加用户名。我的意思是在我页面的侧边栏中,我是 flutter 的新手,所以我在这方面遇到了很大的困难帮助我
我尝试使用共享首选项,但我不能像变量所说的那样做,因为它是未来的字符串。我让它在一个人登录时保存用户名,当我试图取回它时它起作用了我不能
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 ...
}
)
如果您想按照自己的方式进行 - 您可以将 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(),),.....),
更新:
用于在变量中保存名称
String name = '';
@override
void initState() {
super.initState();
_get().then((value) {
setState(() {
name = value;
});
});
}
您可以做的是在 initstate 中获取数据并使用 "then" 关键字将用户名分配给变量并在整个存储中使用该变量,并在 "then" 中构建您的应用程序。它会等到您获得数据,然后构建您的应用程序
为什么不使用安全存储插件?
// 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);