Flutter 如何使用共享首选项读取颤振中所有底部选项卡屏幕的数据
我需要保存数据,然后在所有选项卡中读取数据,并尝试使用共享首选项保存和读取数据。现在我有3个屏幕,它们是登录、主页和配置文件屏幕。在home和profile中,我使用底部选项卡导航器,所以在用户登录后(发布他们的数据,我使用共享首选项保存数据,我希望在home和profile屏幕中访问这些数据)。让我困惑的是。。。单击“登录”按钮后,我将其导航到底部选项卡文件,其中按钮选项卡文件由主屏幕和配置文件屏幕组成,我不知道如何使用共享首选项读取主屏幕和配置文件屏幕中的数据,因为登录后,我将其导航到底部选项卡,而不是主屏幕。这是我的密码 主飞镖Flutter 如何使用共享首选项读取颤振中所有底部选项卡屏幕的数据,flutter,navigation,Flutter,Navigation,我需要保存数据,然后在所有选项卡中读取数据,并尝试使用共享首选项保存和读取数据。现在我有3个屏幕,它们是登录、主页和配置文件屏幕。在home和profile中,我使用底部选项卡导航器,所以在用户登录后(发布他们的数据,我使用共享首选项保存数据,我希望在home和profile屏幕中访问这些数据)。让我困惑的是。。。单击“登录”按钮后,我将其导航到底部选项卡文件,其中按钮选项卡文件由主屏幕和配置文件屏幕组成,我不知道如何使用共享首选项读取主屏幕和配置文件屏幕中的数据,因为登录后,我将其导航到底部选
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginScreen(),
);
}
}
我的登录屏幕
class _LoginScreenState extends State<LoginScreen> {
postData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt('username', _username.text);
Navigator.push(context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new BottomTab()));
}
@override
Widget build(BuildContext context) {
return Column(
children:<Widget>[
TextFormField(
controller: _username),
FlatButton(
child: Text("Login"),
onPressed: () {
postData(_username.text);}),];}
}
class\u LoginScreenState扩展状态{
postData()异步{
SharedReferences prefs=等待SharedReferences.getInstance();
prefs.setInt('username',_username.text);
Navigator.push(上下文,
新材料路线(
生成器:(BuildContext上下文)=>
新的底部选项卡());
}
@凌驾
小部件构建(构建上下文){
返回列(
儿童:[
TextFormField(
控制器:_用户名),
扁平按钮(
子项:文本(“登录”),
已按下:(){
postData(_username.text);}),];}
}
我的底部标签文件
class _BottomTab extends State<BottomTab> {
int _selectedIndex = 0;
_onTap(int index) {
setState(() => _myindex = index);
}
final List<Widget> pages = [
HomeScreen(),
ProfileScreen(),
];
final PageStorageBucket bucket = PageStorageBucket();
Widget _myNavigation(int selectedIndex) => BottomNavigationBar(
onTap: _onTap,
currentIndex: myindex,
type: BottomNavigationBarType.fixed,
items: const <MyTab>[
MyTab(icon: Icon(Icons.home), title: Text('Home')),
MyTab(icon: Icon(Icons.person), title: Text('Profile')),
],
);
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _myNavigation(_myindex),
body: PageStorage(
child: pages[_myindex],
bucket: bucket,
),
);
}
}
class\u BottomTab扩展状态{
int _selectedIndex=0;
_onTap(整数索引){
设置状态(()=>_myindex=index);
}
最终列表页=[
主屏幕(),
ProfileScreen(),
];
final PageStorageBucket bucket=PageStorageBucket();
小部件_myNavigation(int-selectedIndex)=>BottomNavigationBar(
onTap:_onTap,
当前索引:myindex,
类型:BottomNavigationBarType.fixed,
项目:常数[
MyTab(图标:图标(Icons.home),标题:文本(“home”),
MyTab(图标:图标(Icons.person),标题:文本('Profile'),
],
);
@凌驾
小部件构建(构建上下文){
返回脚手架(
底部导航栏:_myNavigation(_myindex),
正文:页面存储(
子:页面[_myindex],
桶:桶,
),
);
}
}
我的主屏幕
class _HomeScreen extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Container(
child: Text("Hello ${...username that I want to pass}"),
);
}
}
class\u主屏幕扩展状态{
@凌驾
小部件构建(构建上下文){
返回容器(
child:Text(“Hello${…我要传递的用户名}”),
);
}
}
您可以在任何地方提取应用程序中的SharedReferences。正如您所说,您还必须访问HomePage和ProfilePage中的SharedReferences数据。因此,您现在有两个选项:
SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
var userName = sharedPrefs.getInt("username")
你可以随时随地提取应用程序中的SharedReferences。正如你所说,你还必须访问HomePage和ProfilePage中的SharedReferences数据。因此,你现在有两个选项:
SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
var userName = sharedPrefs.getInt("username")
您可以选择,每次要显示来自异步源的数据时,都可以使用
FutureBuilder
:
FutureBuilder:
class _HomeScreen extends State<HomeScreen> {
Future<int> _getUsername;
@override
void initState() {
_getUsername = SharedPreferences.getInstance().then((prefs) {
return prefs.getInt("username");
}
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder() {
future: _getUsername,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
// The value is not read yet
return Text("Loading username...");
}
final username = snapshot.data.toString();
return Container(
child: Text("Hello $username"),
);
}
}
}
您可以选择,每次要显示来自异步源的数据时,都可以使用
FutureBuilder
:
FutureBuilder:
class _HomeScreen extends State<HomeScreen> {
Future<int> _getUsername;
@override
void initState() {
_getUsername = SharedPreferences.getInstance().then((prefs) {
return prefs.getInt("username");
}
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder() {
future: _getUsername,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
// The value is not read yet
return Text("Loading username...");
}
final username = snapshot.data.toString();
return Container(
child: Text("Hello $username"),
);
}
}
}
但是,当我单击登录按钮时,我是否需要在底部选项卡中传递用户名?我的意思是,我是否应该在此处传递用户名?
Navigator.push(上下文,new MaterialPageRoute(builder:(BuildContext context)=>new BottomTab(…用户名值(?))
No,这些共享引用本质上是全局的。您可以在整个应用程序中访问这些引用,而无需传递它。但是,当我单击“登录”按钮时,我是否需要在底部选项卡中传递用户名?我的意思是,我是否应该在此处传递用户名?Navigator.push(上下文,new MaterialPageRoute(builder:(BuildContext上下文)=>新的底部选项卡(…用户名值(?))
不,这些共享引用本质上是全局的。您可以在整个应用程序中访问这些引用,而无需传递。我使用FutureBuilder尝试了第一个选择,但我在屏幕上看到了加载用户名…,这是否意味着用户名没有在共享首选项中设置?您确定没有出错吗?应该可以。您将有“Hello null”没有用户名。如果在内部,请检查Conditionalbuilder@uyhaW尝试在postData方法中为setInt添加wait
。我认为您读取值太早。此条件是强制性的,因为您必须在尚未加载数据时返回一个小部件。但是如果您希望避免每次在主屏幕
实例,您必须由父级加载数据。第二种解决方案会更好。当然,您也可以将FutureBuilder
放在BottomTab
中,并将数据传递到主屏幕
constructor@uyhaW我用第三种解决方案编辑了我的文章。这就足够了。但是如果你想传递数据,请点击thr通过该树,提供程序将比向每个构造函数传递数据更简单。我使用FutureBuilder尝试了第一种选择,但我的屏幕中出现了加载用户名…
,这是否意味着用户名没有在共享首选项中设置?你确定没有出错吗?应该可以。你将有“Hello null”没有用户名。如果在内部,请检查Conditional
class _BottomTab extends State<BottomTab> {
// ....
@override
Widget build(BuildContext context) {
return FutureBuilder() {
future: _getUsername,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
// The value is not read yet
return Text("Loading username...");
}
return HomeScreen(snapshot.data.toString());
}
}
}