【问题标题】:Flutter - Stateful Widget Doesn't Save Counter State When Switching TabsFlutter - 有状态的小部件在切换选项卡时不保存计数器状态
【发布时间】:2018-11-24 08:51:04
【问题描述】:

我正在学习颤振,我正在使用 tabBars,但我在保存状态时遇到了问题。我在下面放了一个关于我的问题的小例子。基本上,有一个按钮和一个有状态的计数器。当我单击按钮时,我看到文本字段正确更新。但是,当我切换到不同的选项卡并返回时,文本字段又归零。

我发现如果我将以下行移到 _CounterState 之外,以便将其定义在文件的顶层,那么它可以正常工作。当我切换标签时,当我切换回来时,计数器会保持正确的计数

int _counter = 0;

我觉得这不是执行此操作的合适方法,而且我看到的所有示例都在类中包含变量。谁能给我任何见解?如果它在课堂内,为什么会重置?我应该把它放在课外吗?下面是简化的完整示例。

import 'package:flutter/material.dart';

void main() {
  runApp(new TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new DefaultTabController(
        length: 3,
        child: new Scaffold(
          appBar: new AppBar(
            bottom: new TabBar(
              tabs: [
                new Tab(icon: new Icon(Icons.directions_car)),
                new Tab(icon: new Icon(Icons.directions_transit)),
                new Tab(icon: new Icon(Icons.directions_bike)),
              ],
            ),
            title: new Text('Tabs Demo'),
          ),
          body: new TabBarView(
            children: [
              new Counter(),
              new Icon(Icons.directions_transit),
              new Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

class Counter extends StatefulWidget {
  @override
  _CounterState createState() => new _CounterState();
}

class _CounterState extends State<Counter> {
  int _counter = 0;

  void _increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Row(
      children: <Widget>[
        new RaisedButton(
          onPressed: _increment,
          child: new Text('Increment'),
        ),
        new Text('Count: $_counter'),
      ],
    );
  }
}

下面是计数器移到类外的示例

import 'package:flutter/material.dart';

void main() {
  runApp(new TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new DefaultTabController(
        length: 3,
        child: new Scaffold(
          appBar: new AppBar(
            bottom: new TabBar(
              tabs: [
                new Tab(icon: new Icon(Icons.directions_car)),
                new Tab(icon: new Icon(Icons.directions_transit)),
                new Tab(icon: new Icon(Icons.directions_bike)),
              ],
            ),
            title: new Text('Tabs Demo'),
          ),
          body: new TabBarView(
            children: [
              new Counter(),
              new Icon(Icons.directions_transit),
              new Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

class Counter extends StatefulWidget {
  @override
  _CounterState createState() => new _CounterState();
}

int _counter = 0; //<-- MOVED OUTSIDE THE _CounterState CLASS
class _CounterState extends State<Counter> {


  void _increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Row(
      children: <Widget>[
        new RaisedButton(
          onPressed: _increment,
          child: new Text('Increment'),
        ),
        new Text('Count: $_counter'),
      ],
    );
  }
}

【问题讨论】:

标签: dart flutter stateful statefulwidget


【解决方案1】:

由于_CounterState 小部件在您每次转到给定的 TabView 时都会构建,您需要将 _counter 变量放入状态配置类 (Counter)。

class Counter extends StatefulWidget {
  int _counter = 0;
  @override
  _CounterState createState() => new _CounterState();
}

class _CounterState extends State<Counter> {
  void _increment() {
    setState(() {
      widget._counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Row(
      children: <Widget>[
        new RaisedButton(
          onPressed: _increment,
          child: new Text('Increment'),
        ),
        new Text('Count: ${widget._counter}'),
      ],
    );
  }
}

【讨论】:

  • 有趣的是,我通常会在 _CounterState 小部件中看到带有变量的示例。你怎么知道你必须在柜台前使用widget,就像widget._counter++一样?我想我不会知道的。
  • 从状态控制类访问变量时,您使用widget 变量。
  • 哇!拯救了我的一天...但作为旁注,现在 StatefulWidget 类被标记为不可变,所以最好不要在其中定义非最终变量
【解决方案2】:

因为我使用了一种解决方案AutomaticKeepAliveClientMixin

您需要将此 mixin 与您的 StateFullWidget 状态类一起使用。

您需要将 true 传递给 wantKeepAlive getter 方法。

class SampleWidget extends StatefulWidget {
  @override
  _SampleWidgetState createState() => _SampleWidgetState();
}

class _SampleWidgetState extends State<SampleWidget> with AutomaticKeepAliveClientMixin{
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Container();
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

这将保存您的状态并停止您的小部件重新创建。我已经将它与 TabbarPageView 一起使用,并且运行良好。

【讨论】:

    【解决方案3】:

    将变量放在那个有状态的小部件中,然后每次都将其称为“widget.variable_name”

    【讨论】:

      猜你喜欢
      • 2018-11-20
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      • 2021-07-03
      • 2019-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-06-08
      相关资源
      最近更新 更多