使用StatelessWidget

时间:2019-02-28 13:44:36

标签: dart flutter

我在学习Flutter时发现了一个小问题,我想知道哪种更好的方法来解决它。

这是该问题的非常简单的示例代码:

class SubWidget extends StatelessWidget {
  final void Function() mainOnPressed;

  SubWidget(this.mainOnPressed);

  @override
  Widget build(BuildContext context) => RaisedButton(onPressed: mainOnPressed,);

  void actionA() { /* Do A */ };
  void actionB() { /* Do B */ };
}


class MainWidget extends StatelessWidget {
  final SubWidget _subWidget;

  MainWidget() : _subWidget = SubWidget(_onSubPressed);

  Widget _buildChildA() => RaisedButton(onPressed: _subWidget.actionA,);
  Widget _buildChildB() => RaisedButton(onPressed: _subWidget.actionB,);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        _buildChildA(),
        _buildChildB(),
        _subWidget,
      ]
    );
  }

  void _onSubPressed() { /* Do something */ }
}

上面的代码有一个错误,因为我在MainWidget构造函数中将 _onSubPressed 方法作为参数传递,并且由于初始化未完成而无法完成。

我也无法将 _subWidget 的初始化移到构造函数之外,因为它会给我一个错误,因为它是 final 并且我无法删除 final ,因为在不可变类中有 non-final 成员会得到警告。

出于同样的原因,我不能推迟 SubWidget 类中 mainOnPressed 的初始化。

我考虑过将 _subWidget 成员移至 build()方法内,并将其传递给 _buildChildX()方法,但同时在此示例中非常简单,必须对具有相同问题的多个成员或方法进行操作会比较烦人。

我发现的另一种解决方案是将 _subWidget 成员和两个 _buildChildX()移动到 build()方法中,如下所示代码:

class MainWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final SubWidget _subWidget = SubWidget(_onSubPressed);
    Widget _buildChildA() => RaisedButton(onPressed: _subWidget.actionA,);
    Widget _buildChildB() => RaisedButton(onPressed: _subWidget.actionB,);

    return Column(
      children: <Widget>[
        _buildChildA(),
        _buildChildB(),
        _subWidget,
      ]
    );
  }

  void _onSubPressed() { /* Do something */ }
}

虽然可以按预期工作,但我有点担心使用嵌套在build方法中的更长,更复杂的方法编写代码的可读性。

哪个是解决此问题的最佳方法?

1 个答案:

答案 0 :(得分:0)

您收到错误“此表达式的类型为 'void',因此无法使用其值的原因。”在 MainWidget() : _subWidget = SubWidget(_onSubPressed()); 上是因为 _onSubPressed() 可能包含意外的表达式。错误消息中提供的链接对此进行了解释:https://dart.dev/tools/diagnostic-messages#use_of_void_result

为了解决这个问题,您可以将函数的内容移动到构造函数中来初始化_subWidget

final SubWidget _subWidget;

MainWidget() : _subWidget = SubWidget((){
  // Do something
});

这是一个完整的示例,您可以试用。

import 'package:flutter/material.dart';

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

class SubWidget extends StatelessWidget {
  final void Function() mainOnPressed;

  SubWidget(this.mainOnPressed);

  @override
  Widget build(BuildContext context) => ElevatedButton(
        child: Text('SubWidget'),
        onPressed: mainOnPressed,
      );

  void actionA() {
    /* Do A */
    debugPrint('Child A');
  }

  void actionB() {
    /* Do B */
    debugPrint('Child B');
  }
}

class MainWidget extends StatelessWidget {
  final SubWidget _subWidget;

  MainWidget() : _subWidget = SubWidget((){
    debugPrint('SubWidget');
  });

  Widget _buildChildA() => ElevatedButton(
        child: Text('Child A'),
        onPressed: _subWidget.actionA,
      );
  Widget _buildChildB() => ElevatedButton(
        child: Text('Child B'),
        onPressed: _subWidget.actionB,
      );

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(children: <Widget>[
            _buildChildA(),
            _buildChildB(),
            _subWidget,
          ]),
        ),
      ),
    );
  }
}