Flutter如何将携带字符串的Drawer传递到下一页面且避免空值
问题原因分析
核心有两个问题导致版本号显示为空:
- 异步执行时序问题:
PackageInfo.fromPlatform()是异步方法,你在initState中触发调用后,方法还没返回结果,FirstPage就已经执行了首次build,这时候构建Drawer用的是初始值为空的packageAppVersion。 - Widget缓存导致无法更新:你直接把预构建好的Drawer实例作为参数传给
SecondPage,并且存在了SecondPage的state中。即使后续FirstPage拿到版本号触发setState更新,生成的新Drawer也无法同步到SecondPage,因为SecondPage用的一直是首次build时生成的旧Drawer实例。
另外代码里还有个坏实践:不要把Widget属性手动存到State中,State中可以直接通过widget.xxx访问父组件传入的属性,手动存储会导致属性更新时State无法拿到最新值。
修正方案
不要提前构建Drawer实例传递,改为直接传递版本号参数,Drawer在SecondPage内部实时构建,同时增加加载判断,等版本号获取成功后再进入第二页,修正后的完整代码如下:
import 'package:flutter/material.dart'; import 'package:package_info/package_info.dart'; void main() { runApp(FirstPage()); } class FirstPage extends StatefulWidget { final String title; FirstPage({Key key, this.title}) : super(key: key); @override _FirstPageState createState() => _FirstPageState(); } class _FirstPageState extends State<FirstPage> { String packageAppVersion = ''; @override void initState() { super.initState(); versionCheck(); } Future<void> versionCheck() async { PackageInfo packageInfo = await PackageInfo.fromPlatform(); setState(() { packageAppVersion = packageInfo.version; }); } @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Drawer Demo', theme: ThemeData( primarySwatch: Colors.blue, ), // 版本号未获取时显示加载页 home: packageAppVersion.isEmpty ? const Scaffold(body: Center(child: CircularProgressIndicator())) : SecondPage( title: 'Second Page', appVersion: packageAppVersion, ), ); } } class SecondPage extends StatefulWidget { final String title; final String appVersion; SecondPage({Key key, this.title, this.appVersion}) : super(key: key); @override _SecondPageState createState() => _SecondPageState(); } class _SecondPageState extends State<SecondPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.title)), // 内部实时构建Drawer,使用最新的版本号 endDrawer: Drawer( child: Padding( padding: const EdgeInsets.all(10.0), child: Column( children: [ Flexible( child: ListView( children: <Widget>[], ), ), Flexible( flex: 0, child: Text("App version: ${widget.appVersion}"), ) ], ), ), ), body: Container(), ); } }
内容的提问来源于stack exchange,提问作者Florentin Lupascu
相关产品推荐
相关产品推荐

