在重建时 Flutter 重用 StatefulWidget 的状态

Posted

技术标签:

【中文标题】在重建时 Flutter 重用 StatefulWidget 的状态【英文标题】:Flutter reuse state from StatefulWidget on rebuild 【发布时间】:2020-12-18 20:16:55 【问题描述】:

简而言之,问题是:如何重用整个小部件子树的状态?


这是我的代码目前的样子:

...
BlocBuilder<AuthBloc, AuthState>(
  builder: (context, state) 
    if (state is Authenticating) 
      return AppLoading();
     else if (state is NotAuthenticated) 
      return AppOnboarding();
     else if (state is Authenticated) 
      return AppMain();
     else 
      return null;
    
  
),
...

这里没什么特别的,只是一个 BlocBuilder 在底层 Bloc 的状态发生变化时重建它的子节点。

现在,以以下状态转换为例:NotAuthenticated =&gt; Authenticating =&gt; NotAuthenticated,因为输入的信息有问题。这将导致 AppOnboarding() 小部件从头开始完全重建,所有信息都丢失了。如何重用旧 AppOnboarding() 小部件的状态,使其看起来像从未重建过的小部件?


我已经尝试过的

我已经尝试过为此使用GlobalKey,我会将其传递给我的 AppOnboarding 小部件的 key 属性。这是我的代码:

_AuthenticatingState extends State<Authenticating> 
  GlobalKey<AppOnboardingState> _appOnboardingKey;

  @override
  initState() 
    super.initState();
    _appOnboardingKey = GlobalKey();
  

  @override
  Widget build(BuildContext context) 
    return BlocBuilder<...>(
      builder: (context, state) 
        ...
        if (state is NotAuthenticated) 
          return AppOnboarding(key: _appOnboardingKey);
        
        ...
      
    ),
  

我有点惊讶这不起作用。全局键不维护条目小部件子树的状态吗?

【问题讨论】:

【参考方案1】:

Flutter 以每秒 60 帧的速度运行。该键告诉 Flutter 某些小部件与上一帧中存在的小部件相同。如果您删除了一些小部件,即使是单个框架,它也会释放小部件(调用 dispose 方法并删除小部件)。

换句话说,密钥不会“保存”任何状态以供以后使用。

你有两个选择:

    根本不丢弃小部件。
builder: (context, state) 
    return Stack(children: [
    Offstage(child:AppLoading(), offstage: state is! Authenticating),
    Offstage(child:AppOnboarding()), offstage: state is! NotAuthenticated),
    Offstage(child:AppMain()), offstage: state is! Authenticated),
    ]) 
  
    保存自己的小部件状态,以便您以后可以使用相同的信息重建小部件。

【讨论】:

以上是关于在重建时 Flutter 重用 StatefulWidget 的状态的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 使用 MediaQuery 时防止重建

Flutter:BottomNavigationBar在选项卡更改时重建页面

在 Flutter 中推送新页面时,Navigator 堆栈上的页面会重建

Flutter StatefulWidget 没有被重建

使用上下文和观察更改模型时,Flutter Provider 不会触发重建

Flutter:单击 TextField 时,推送的 LoginScreen 小部件正在重建 UI