在 flutter 中从另一个 class 的有状态小部件中获取整数值

Get the value of an integer from a stateful widget from another class in flutter

学习 Flutter,我正在构建一个我想用于购物车的计数器。我在检索我创建的计数器有状态小部件的整数值时遇到问题,我希望文本使用计数器的值更新自身。

这是计数器的代码

import 'package:flutter/material.dart';

class TheCounter extends StatefulWidget {
  int counter = 0;
  int get counterValue => counter;

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

class _TheCounterState extends State<TheCounter> {
  void increaseCounter() {
    setState(() {
      if (widget.counter >= 0) {
        widget.counter++;
      }
    });
  }

  void decreaseCounter() {
    setState(() {
      if (widget.counter > 0) {
        widget.counter--;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        IconButton(icon: Icon(Icons.add), onPressed: increaseCounter),
        Text('${widget.counter}'),
        IconButton(icon: Icon(Icons.remove), onPressed: decreaseCounter)
      ],
    );
  }
}

这里是 main.dart 文件

import 'package:counter/counter.dart';
import 'package:flutter/material.dart';

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

class Count extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    int counting = TheCounter().counterValue;
    return MaterialApp(
      title: 'Counter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Counter Test'),
        ),
        body: Column(
          children: [
            TheCounter(),
            Text('$counting'),
            TheCounter(),
            TheCounter(),
          ],
        ),
      ),
    );
  }
}

我希望每当单击添加或删除按钮时,文本都会使用计数器的值更新自身。我该怎么做才能做到这一点?

首先,我们需要决定在哪里进行更新。在这种情况下,Count 小部件文本需要更新。 因此,需要将其转换为 StatefulWidget.

接下来是我们如何从 TheCounter 小部件中检索计数器。您可以使用回调方法,或状态管理包,如 provider、riverpod、bloc 等。您可以查看 doc

这里我使用了一个函数,只要 TheCounter 小部件上的计数值发生变化,它就会在 Count 上获取更新值。


void main() {
  runApp(MaterialApp(title: 'Counter', home: Count()));
}

class Count extends StatefulWidget {
  const Count({Key? key}) : super(key: key);

  @override
  State<Count> createState() => _CountState();
}

class _CountState extends State<Count> {
  int initNumberOfCounter = 4;

  late List<int> countersValue = List.generate(initNumberOfCounter, (index) => 0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter Test'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            countersValue.add(0);
          });
        },
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              itemCount: countersValue.length,
              itemBuilder: (context, index) {
                return Row(
                  // mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    TheCounter(
                      initCountValue: countersValue[index],
                      countValueCallback: (v) {
                        setState(() {
                          countersValue[index] = v;
                        });
                      },
                    ),
                    const SizedBox(
                      width: 40,
                    ),
                    Text("${countersValue[index]}"),
                  ],
                );
              },
            ),
          )
        ],
      ),
    );
  }
}

class TheCounter extends StatefulWidget {
  final Function(int) countValueCallback;
  final int initCountValue;
  const TheCounter({
    Key? key,
    required this.countValueCallback,
    this.initCountValue = 0,
  }) : super(key: key);

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

class _TheCounterState extends State<TheCounter> {
  ///this use within the current state
  late int counter;

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

    ///set counter value for the 1st time
    counter = widget.initCountValue;
  }

  void increaseCounter() {
    setState(() {
      if (counter >= 0) {
        counter++;
      }
    });

    /// back to parent widget
    widget.countValueCallback(counter);
  }

  void decreaseCounter() {
    setState(() {
      if (counter > 0) {
        counter--;
      }
    });
    widget.countValueCallback(counter);
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        IconButton(icon: Icon(Icons.add), onPressed: increaseCounter),
        Text('${counter}'),
        IconButton(icon: Icon(Icons.remove), onPressed: decreaseCounter)
      ],
    );
  }
}