颤动 - 状态小部件在切换选项卡时不保存计数器状态

时间:2018-06-14 14:26:02

标签: dart flutter stateful statefulwidget

我正在学习扑克,我正在使用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'),
      ],
    );
  }
}

3 个答案:

答案 0 :(得分:5)

每当您转到给定的TabView时,都会构建_CounterState窗口小部件,您需要将_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}'),
      ],
    );
  }
}

答案 1 :(得分:1)

当我使用一种解决方案AutomaticKeepAliveClientMixin

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

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

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

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

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

这将保存您的状态并停止您的窗口小部件以重新创建。我已经将它与 Tabbar PageView 一起使用,并且工作正常。

答案 2 :(得分:0)

将变量放入该statefulwidget中,然后每次将其称为“ widget.variable_name”