如何使构建函数在 Flutter 中等待异步函数?

How to make build function wait async function in Flutter?

小部件构建函数不等待异步函数更新变量值,这对于脚手架 webview link 是必不可少的。我试图将异步函数移动到代码的不同部分,但似乎没有任何效果。将变量打印到控制台时,首先打印空值,然后打印实际值。这里有什么问题?

class ProfilePage extends StatefulWidget {
  const ProfilePage({Key? key}) : super(key: key);

  @override
  State<ProfilePage> createState() => _ProfilePageState();
}

class _ProfilePageState extends State<ProfilePage> {
  var phone;
  var password;
  @override
  void initState() {
    super.initState();
    retrieveStringValue();
  }

  retrieveStringValue() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      password = prefs.getString("password");
      phone = prefs.getString("phone");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: false,
      body: SafeArea(
        child: WebView(
          javascriptMode: JavascriptMode.unrestricted,
          initialUrl:
              'https://turon.com/app_login.php?phone=$phone&password=$password',
        ),
      ),
    );
  }
}

您可以为此使用 FutureBuilder。您还可以稍微简化它并使用 StatelessWidget.

在这里,我将您的 retrieveStringValue 函数更改为 return a Map,其中包含 FutureBuilder 将用于显示数据的存储值。

class ProfilePage extends StatelessWidget {
  const ProfilePage({Key? key}) : super(key: key);

  Future<Map<String, String>?> retrieveStringValue() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final password = prefs.getString("password");
    final phone = prefs.getString("phone");

    final bool hasData = password != null && phone != null;

    if (hasData) {
      return {
        'password': password,
        'phone': phone
      }; // this return value is accessed via snapshot.data in FutureBuilder
    } else {
      return null; // null tells FutureBuilder that no data is stored
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: false,
      body: SafeArea(
        child: FutureBuilder(
          future: retrieveStringValue(), // returns a Map with the stored values
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              final map = snapshot.data! as Map<String, String>;
              final password = map['password'];
              final phone = map['phone'];
              return WebView(
                javascriptMode: JavascriptMode.unrestricted,
                initialUrl:
                    'https://turon.com/app_login.php?phone=$phone&password=$password',
              );
            } else {
              return Center(child: CircularProgressIndicator()); // or an indicator that no data is stored
            }
          },
        ),
      ),
    );
  }
}