Flutter:如何从另一个小部件更改/刷新状态

时间:2021-03-11 20:54:40

标签: flutter

我正在尝试在小部件中显示一个全局整数,然后通过来自另一个小部件的某些内容(单击按钮或其他内容)进行更新。我尝试过的所有其他方法都不起作用。这样做的最佳方法是什么?

堆栈溢出说我有太多的代码所以更多的文字更多的文字更多的文字

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: Container(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ScoreDisplay(),
              PointButton(),
            ],
          ),
        ),
      ),
    ),
  );
}

int score = 0;

class ScoreDisplay extends StatefulWidget {
  @override
  _ScoreDisplayState createState() => _ScoreDisplayState();
}

class _ScoreDisplayState extends State<ScoreDisplay> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: Text(
          'Score: $score',
        ),
      ),
    );
  }
}

class PointButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: RaisedButton(
          //onPressed: //increment score,
        ),
      ),
    );
  }
}

2 个答案:

答案 0 :(得分:1)

您需要为此实施某种状态管理。

enter image description here

以下是实现此类功能的两种基本方法:使用 StatefulWidget 和使用 Riverpod

1.使用 StatefulWidget

我提取了您的 Scaffold 作为 StatefulWidget 维护您的应用程序的 score

然后我使用 ScoreDisplay 作为纯 StatelessWidget 接收 score 作为参数。并且您的 PointButton 也是无状态的,并通过简单的 ScorePage 函数调用 VoidCallback

完整源代码:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: ScorePage(),
    ),
  );
}

class ScorePage extends StatefulWidget {
  const ScorePage({
    Key key,
  }) : super(key: key);

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

class _ScorePageState extends State<ScorePage> {
  int score = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ScoreDisplay(score: score),
            PointButton(onIncrement: () => setState(() => score++)),
          ],
        ),
      ),
    );
  }
}

class ScoreDisplay extends StatelessWidget {
  final int score;

  const ScoreDisplay({Key key, this.score}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: Text(
          'Score: $score',
        ),
      ),
    );
  }
}

class PointButton extends StatelessWidget {
  final VoidCallback onIncrement;

  const PointButton({Key key, this.onIncrement}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: ElevatedButton(
          onPressed: () => onIncrement?.call(),
          child: Text('CLICK ME'),
        ),
      ),
    );
  }
}

2.与 Riverpod

创建一个StateProvider

final scoreProvider = StateProvider<int>((ref) => 0);

观看StateProvider

final score = useProvider(scoreProvider).state;

更新 StateProvider

context.read(scoreProvider).state++

完整源代码

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

void main() {
  runApp(
    ProviderScope(
      child: MaterialApp(
        home: Scaffold(
          body: Container(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ScoreDisplay(),
                PointButton(),
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

int score = 0;

class ScoreDisplay extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final score = useProvider(scoreProvider).state;
    return Center(
      child: Container(
        child: Text(
          'Score: $score',
        ),
      ),
    );
  }
}

class PointButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: ElevatedButton(
          onPressed: () => context.read(scoreProvider).state++,
          child: Text('CLICK ME'),
        ),
      ),
    );
  }
}

final scoreProvider = StateProvider<int>((ref) => 0);

查看 Riverpod Website 了解更多信息和更高级的用例。

但你有many more flavors of State Management available

答案 1 :(得分:1)

最好的例子是使用可以在 www.pub.dev 上找到的“provider”包 这是一个非常简单的状态管理包,可以帮助您解决这个问题。保持在我的那个提供者而不是 setState() 中使用 notifyListener()