如何将Flutter页面(Widget)重置为初始状态(即应用程序首次构建时的状态)

8
假设我在页面上有几个滑块和开关,我改变它们的状态并修改它们。我知道我们会使用setState来显示小部件树的更改状态并重建它,但我想知道是否有一种方法可以撤消所有这些更改并返回到初始状态(应用程序在首次构建时的状态)?我不想调用自定义函数手动将变量重置为初始值。也不应该移除并添加回路由(因为这会显示转换)。

如果您在initState中初始化了所有状态,那么您可以像调用setState一样再次调用它 :) - Saed Nabil
寻求来自可靠来源的答案,展示正确的做法。 - Mahesh Jamdade
7个回答

17
如果你想要做一些非常规的事情。

enter image description here


简短回答:

可以使用以下任意一个:

Navigator.pushReplacementNamed(context, '/currentRoute');
Navigator.popAndPushNamed(context, '/currentRoute');

详细回答:

void main() => runApp(MaterialApp(home: DummyWidget()));

class DummyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) => HomePage();
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool _enabled = false; // For Switch
  double _value = 0; // For Slider

  // This is the trick!
  void _reset() {
    Navigator.pushReplacement(
      context,
      PageRouteBuilder(
        transitionDuration: Duration.zero,
        pageBuilder: (_, __, ___) => DummyWidget(),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Switch(
            value: _enabled,
            onChanged: (newValue) => setState(() => _enabled = newValue),
          ),
          Slider(
            value: _value,
            onChanged: (newValue) => setState(() => _value = newValue),
          ),
          TextButton(
            onPressed: _reset,
            child: Text('RESET'),
          ),
        ],
      ),
    );
  }
}

更好的方法可能是使用键。这里是键方法


8
一个简单的技巧是使用相同的路由进行弹出和推入。像这样:

Navigator.popAndPushNamed(context, "same_route");

6

截图:

enter image description here


使用key来改变状态。
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: KeyedSubtree(
        key: ValueKey<int>(_count),
        child: Column(
          children: [
            MainPage(),
            ElevatedButton(
              onPressed: () => setState(() => ++_count),
              child: Text('RESET'),
            )
          ],
        ),
      ),
    );
  }
}

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  bool _enabled = false; // For Switch
  double _value = 0; // For Slider.

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Switch(
          value: _enabled,
          onChanged: (newValue) => setState(() => _enabled = newValue),
        ),
        Slider(
          value: _value,
          onChanged: (newValue) => setState(() => _value = newValue),
        ),
      ],
    );
  }
}

1
旧键的小部件会发生什么?它们会被垃圾回收吗? - NullByte08
对我来说,这是最好的方法,因为我有一个内部组件,每次在父组件中更改输入时,我都必须重置所有动画。 - DeividSilva
这对我来说是最好的方法,我有一个内部组件,每次在父组件中更改输入时,我都必须重置所有动画。 - undefined

1

在这种情况下,有几个古老的设计模式可能会很有用。拥有重置选项很酷,但更酷的是撤消

请参阅这些教程,了解如何在Flutter中实现命令(Command)备忘录(Memento)模式: Command | Memento


1
这是许多方法中的一种,可以重置为初始数据。

enter image description here

import 'package:flutter/material.dart';

List<String> initialData = ['First', 'Second', 'Third'];

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: Example(),
    );
  }
}

class Example extends StatefulWidget {
  @override
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
  List<String> items = [];

  @override
  void initState() {
    fillInitialData();
    super.initState();
  }

  fillInitialData() {
    items.addAll(initialData);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Example')),
      body: Column(
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              itemCount: items.length,
              itemBuilder: (context, index) {
                return Card(
                  child: Padding(
                    padding: EdgeInsets.all(16.0),
                    child: Text(items[index]),
                  ),
                );
              },
            ),
          ),
          Row(
            children: <Widget>[
              FlatButton(
                onPressed: () {
                  setState(() {
                    items.add('A new item');
                  });
                },
                child: Text('Add an item'),
              ),
              FlatButton(
                onPressed: () {
                  setState(() {
                    items.clear();
                    fillInitialData();
                  });
                },
                child: Text('Reset'),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

1
这个答案更具体地针对您的用例和数据结构。我正在寻找一种通用的方法来重置页面活动。 - Mahesh Jamdade
这是相同的思路,声明变量,分配初始值,然后在需要时重置。如果您想完全重置小部件,可以从其父级调用setState并传递您的初始数据。 示例(名称:'maheshmnj',奖项:[...])。正如我所说,有许多实现您想要的方法。 - HasanAlyazidi

1

屏幕截图:

enter image description here

完整代码:
void main() {
  runApp(
    MaterialApp(
      // Passing initial values
      home: HomePage(enabled: false, value: 0),
    ),
  );
}

class HomePage extends StatefulWidget {
  final bool enabled;
  final double value;

  HomePage({this.enabled = false, this.value = 0});

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool _initialEnabled, _enabled; // For Switches
  double _initialValue, _value; // For Sliders

  @override
  void initState() {
    super.initState();

    // Assign them once (initial data)
    _initialEnabled ??= widget.enabled;
    _initialValue ??= widget.value;

    // These values can be changed by respective widgets
    _enabled = _initialEnabled;
    _value = _initialValue;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [
            Switch(
              value: _enabled,
              onChanged: (value) => setState(() => _enabled = value),
            ),
            Slider(
              value: _value,
              onChanged: (value) => setState(() => _value = value),
            ),
            RaisedButton(
              onPressed: () {
                setState(() {
                  // Resetting the values to initial ones which were passed
                  _enabled = _initialEnabled;
                  _value = _initialValue;
                });
              },
              child: Text('RESET'),
            ),
          ],
        ),
      ),
    );
  }
}

0

您可以调用 YourStateClass.initState() 方法将其恢复为初始状态。

此外,在构造状态时,请确保您在 void initState() 函数中初始化所有变量。

例如:

class FooState extends State<Foo> { 
    int someVariable;

    @override
    void initState() {
        someVariable = 0;
    }
}

为了使其正常工作,您需要在initState()函数中为所有变量分配一个值。

欲了解更多信息,请查看文档https://api.flutter.dev/flutter/widgets/State/initState.html


final不能被重新赋值。应该使用int someVariable; - HasanAlyazidi
这对我没有起作用。使用PageRouteBuilder解决了问题。 - chitgoks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接