如何使用共享首选项在颤振中读取所有底部选项卡屏幕的数据

How to use shared preferences to read data for all bottom tabs screen in flutter

我需要保存我的数据,然后在所有选项卡中读取它,我尝试使用共享首选项保存和读取我的数据。现在我有 3 个屏幕,它们是登录、主页和个人资料屏幕。在主页和个人资料中,我使用底部选项卡导航器,因此在用户登录后(post 他们的数据,我使用共享首选项保存该数据,我想在主页和个人资料屏幕中访问该数据)。让我感到困惑的是...单击登录按钮后,我将其导航到 BottomTab 文件,其中 ButtomTab 文件由主屏幕和配置文件屏幕组成,我对如何使用共享首选项在主屏幕和配置文件屏幕中读取我的数据感到困惑,因为登录后,我将它导航到我的 BottomTab,而不是我的主屏幕。这是我的代码 main.dart

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);}),];}
}

我的 BottomTab 文件

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 _HomeScreen extends State<HomeScreen> {
@override
  Widget build(BuildContext context) {

    return Container(
      child: Text("Hello ${...username that I want to pass}"),
    );
  }
}

您可以在应用中的任何位置提取 SharedPreferences。正如您所说,您还必须访问 HomePage 和 ProfilePage 中的 SharedPreferences 数据。所以你现在有两个选择:

  1. 您可以在 BottomTab 页面中提取您的共享首选项并将其传递到主页和 ProfilePage。
  2. 此外,您可以分别提取两个页面中的 SharedPreference。

提取SharedPreference可以参考下面的代码:

SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
var userName = sharedPrefs.getInt("username")

你有选择,每次你想显示来自异步源的数据时你可以使用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"),
      );
    }
  }
}

或者您可以使用提供程序包 https://pub.dev/packages/provider 来公开小部件树中的值:

class _BottomTab extends State<BottomTab> {
// ....

  @override
  Widget build(BuildContext context) {
    return FutureProvider<int>(
      create: (context) async {
        final prefs = await SharedPreferences.getInstance();
        return prefs.getInt("username");
      },

      child: Scaffold(
        bottomNavigationBar: _myNavigation(_myindex),
        body: PageStorage(
          child: pages[_myindex],
          bucket: bucket,
        ),
      );
    }
  }
}

并读取读取值:

Widget build() {
  final username = Provider.of<int>(context).toString();

  if (username == null) {
    // The value is not read yet
    return "Loading username...";
  }

  return Text("Username is $username");
}

FutureProvider 的值更新时将再次调用构建方法


编辑:第三个解决方案

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