design-patterns - 如何定义抽象小部件?

标签 design-patterns flutter dart

由于 Dart/Flutter 使用组合风格的方法来构建小部件(将其与作用域模型的操作方式相结合),开发封装小部件的对象库的良好模式是什么?

假设您有一个应用程序,允许您在 ListView 中显示对象列表,每个对象都有自己的方式来显示它们的信息,但都采用相同的方法来实现。

考虑以下伪代码,它采用封装所有必需的小部件和每个对象所需的其他此类属性/方法的方法。

abstract class Vehicle {
  int type;
  String name;
  Widget listWidget
  Widget editWidget
  Widget settingsWidget
}

class Truck extends Vehicle {
  type = 1
  name = "Truck"
  listWidget = ... My truck widget for within lists...
  editWidget = ... My truck edit widget ...
  settingsWidget = ... My truck settings display ...
}

class Car extends Vehicle {
  type = 1
  name = "Car"
  listWidget = ... My car widget for within lists...
  editWidget = ... My car edit widget ...
  settingsWidget = ... My car settings display ...
}

使用这种方法,我将不得不创建每种车辆类型并遵循抽象的 api 模式,而不用担心它是如何呈现的。

当谈到在列表(例如 ListView)中显示车辆时,这种方法允许对象本身决定它在该列表中的呈现方式,并且它对于每种类型的车辆可能是唯一的。

例如:

    Container(
        child: new ListView.builder(
            itemCount: items.length,
            itemBuilder: (BuildContext ctxt, int index) {
                return items[index].listWidget;
            }
        )
    )

这是实现此目的的有效 Dart/Flutter 方法还是应该遵循更好的模式?

我是否违反了 Dart 推荐的编码模式,因为每个小部件都会控制它自己的显示?

这背后的想法是,如果需要根据车辆类型对设置面板进行不同的格式化,我可以做到,而不是试图弄清楚如何为所有小部件创建通用的显示模式。

想法?

最佳答案

我想你真正想要的是这样的东西,我将使用 Flutter Dart 代码而不是伪代码:

class Vehicle extends StatelessWidget {
  final int type;
  final String name;
  final Widget list, edit, settings;

  const Vehicle({Key key, this.type, this.name, this.list, this.edit, this.settings}) : super(key: key);

  @override
  Widget build(BuildContext context) => Row(children: <Widget>[list, edit, settings]);
}

class Truck extends StatelessWidget {
  const Truck({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => Vehicle(
        type: 1,
        name: 'Truck',
        list: Column(),
        edit: const Icon(Icons.edit),
        settings: Checkbox(),
      );
}

class Car extends StatelessWidget {
  const Car({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => Vehicle(
    type: 2,
    name: 'Car',
    list: Column(),
    edit: const Icon(Icons.edit_location),
    settings: ToggleButtons(...),
  );
}

如您所见,您可以拥有一个预定义的 Vehicle 类,它定义参数并处理布置您想要为不同车辆动态显示的所有信息。
现在,您可以通过创建另一个在其构建方法中返回 Vehicle 的小部件来实现特定的车辆。

显然,我选择的布局小部件RowColumn 等只是作为占位符,但您实际上可以使用这种方法实现您的布局逻辑。

我会说这是一种更惯用的小部件方法。


关于您的示例:在使用 ListView.builder 时,您可能不应该将小部件存储在 List 中,但您可以在 builder< 中动态实例化您的小部件功能。如果您可以使用 ListView.builder,这在性能方面也会更好。如果你不能动态创建你的项目,你可以使用 ListView而是将您的小部件存储在列表中。

builder: () {
  if (items[index]['type'] == 'car')
    return Car(...);

  return Truck(...);
}

关于design-patterns - 如何定义抽象小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58632550/

相关文章:

javascript - 我如何在 firestore 字段的数组字段中循环并检索最后一个对其具有真实值(value)的结果?

c - 这个解析器设计模式叫什么?使用包含关键字和函数指针的结构数组的解析器?

c++ - 全局变量 "things"和 "single"?

dart - Flutter - 显示来自相机的本地镜像

dart - 在 Flutter 中从底部导航栏进行整页路由

dart - 如何在 VSCode 中重命名 dart 文件?

objective-c - 在提交之前使用 Singleton 来跟踪表单数据。 . .好主意?

java - 实例化非最终静态变量是线程安全的吗?

flutter - 如果我在 Flutter 中只使用一些 Statefulwidgets 会怎样?

android - “SystemChrome”未在 Flutter 中定义