Flutter - 如何提取带有onPressed setState的部件?

4

我想提取一个内含onPressedsetState的部件,但是我得到了这个信息:“无法提取封闭类方法的引用。” 有没有办法做到这一点?

我想把我的代码分成不同的小部件,以便它保持清晰。这里是一个简化的代码示例:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Calculator(),
    );
  }
}

class Calculator extends StatefulWidget {
  @override
  _CalculatorState createState() => _CalculatorState();
}

class _CalculatorState extends State<Calculator> {
  var myValue = 0;

  void calculate() {
    myValue = 12;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            child: TextButton(
              onPressed: () {
                setState(() {
                  calculate();
                });
              },
              child: Text(
                'Button 001',
              ),
            ),
          ),
          TextOutput(myValue: myValue),
        ],
      ),
    );
  }
}

class TextOutput extends StatelessWidget {
  const TextOutput({
    Key key,
    @required this.myValue,
  }) : super(key: key);

  final int myValue;

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(
        myValue.toString(),
      ),
    );
  }
}

我想将其提取到一个单独的小部件中:
  Container(
    child: TextButton(
      onPressed: () {
        setState(() {
          calculate();
        });
      },
      child: Text(
        'Button 001',
      ),
    ),
  ),
3个回答

5

Flutter提供VoidCallback和Function(x)(其中x可以是不同的类型)用于子widget和父widget之间的回调事件。

简单地说,您可以通过构造函数传递Function onPressed; 这是您提取的Container widget:

class ExtractedContainer extends StatelessWidget {
  final Function onPressed;
  const ExtractedContainer({
    Key key, @required this.onPressed,
  }) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
      child: TextButton(
        onPressed: () {
          onPressed();
        },
        child: Text(
          'Button 001',
        ),
      ),
    );
  }
}

下面是如何使用它:

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ExtractedContainer(onPressed: calculate,),
          TextOutput(myValue: myValue),
        ],
      ),
    );
  }

您的完整代码示例

import 'package:flutter/material.dart';

class MyApp2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Calculator(),
    );
  }
}

class Calculator extends StatefulWidget {
  @override
  _CalculatorState createState() => _CalculatorState();
}

class _CalculatorState extends State<Calculator> {
  var myValue = 0;

  void calculate() {
    myValue = 12;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ExtractedContainer(onPressed: calculate,),
          TextOutput(myValue: myValue),
        ],
      ),
    );
  }
}

class ExtractedContainer extends StatelessWidget {
  final Function onPressed;
  const ExtractedContainer({
    Key key, @required this.onPressed,
  }) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
      child: TextButton(
        onPressed: () {
          onPressed();
        },
        child: Text(
          'Button 001',
        ),
      ),
    );
  }
}

class TextOutput extends StatelessWidget {
  const TextOutput({
    Key key,
    @required this.myValue,
  }) : super(key: key);

  final int myValue;

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(
        myValue.toString(),
      ),
    );
  }
}

0

SetState与您要刷新其状态的小部件有关。如果您将其提取到另一个地方,那么setState将引用新小部件的状态。

在您的情况下,setState仅会更改包含您正在尝试提取和其子级的小部件所封装的容器的状态,而不会向上迁移。

除非您使用exact type查找所需小部件的状态,然后触发该状态,但这是过度设计,比当前拥有的代码需要更多的代码,并且更难以实现。


0

您可以在提取小部件上使用VoidCallback来获取onPressed事件

class MyContainer extends StatelessWidget {
  final VoidCallback onTap;
  const MyContainer({
    Key? key,
    required this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: TextButton(
        onPressed: onTap,
        child: Text(
          'Button 001',
        ),
      ),
    );
  }
}

并且像这样使用

          MyContainer(
            onTap: () {
              print("tapped");

              setState(() {
                calculate();
              });
            },
          ),

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