如何使用Flutter使用VoidCallback和Function(x)在Widget之间进行通信

来自菜鸟教程
跳转至:导航、​搜索

介绍

Flutter 项目的一个很好的范例是将你的小部件分成小的、可测试的单元,这些单元可以适应它们的上下文。

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

在本文中,您将使用回调样式的事件与 Flutter 进行小部件之间的通信。

先决条件

要阅读本文,您将需要:

  • 下载并安装 Flutter
  • 下载并安装Android Studio Visual Studio Code
  • 建议为您的代码编辑器安装插件: 为 Android Studio 安装了 Flutter 和 Dart 插件。 为 Visual Studio Code 安装了 Flutter 扩展。

本文已使用 Flutter v1.22.2、Android SDK v30.0.2 和 Android Studio v4.1 进行了验证。

第 1 步 — 设置项目

为 Flutter 设置好环境后,您可以运行以下命令来创建新应用程序:

flutter create flutter_widget_communication

导航到新的项目目录:

cd flutter_widget_communication

使用 flutter create 将生成一个演示应用程序,该应用程序将显示按钮被单击的次数。

您将基于生成的代码来试验回调样式事件。

第 2 步 — 将数据从父小部件传递到子小部件

您将创建一个父窗口小部件 (CounterPage) 和一个子窗口小部件 (Count)。 父级的 count 值将显示在子级中。

在代码编辑器中打开 main.dart 并修改它以使用 CounterPage()

lib/main.dart

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Widget Communication',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: CounterPage(),
    );
  }
}

此代码将显示 CounterPage

创建一个新的 counter_page.dart 文件并添加以下代码行:

lib/counter_page.dart

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

class CounterPage extends StatefulWidget {
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Widget Communication")),
      body: Center(
        child: Count(count),
      ),
    );
  }
}

此代码会将 count 传递给子小部件。

创建一个新的 count.dart 文件并添加以下代码行:

lib/count.dart

import 'package:flutter/material.dart';

class Count extends StatelessWidget {
  final int count;

  Count(this.count);

  @override
  Widget build(BuildContext context) {
    return Text("$count");
  }
}

编译你的代码并让它在模拟器中运行:

这将在屏幕上显示 count(当前设置为数字零)。

接下来,您将添加一个 VoidCallback

第 3 步 — 使用 VoidCallback

出于本教程的目的,您将需要创建一个 Button 来注册点击并通知父级 CounterPage

由于您不想在此处返回值,因此您需要注册一个 VoidCallback。 您还将为 Count 构造函数中的项目添加大括号,以使它们成为 命名参数

重新访问 count.dart 并添加 onCountSelected

lib/count.dart

class Count extends StatelessWidget {
  final int count;
  final VoidCallback onCountSelected;

  Count({
    @required this.count,
    this.onCountSelected,
  });

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text("$count"),
      onPressed: () => onCountSelected(),
    );
  }
}

然后,重新访问 counter_page.dart 并监听 onCountSelected 回调:

lib/counter_page.dart

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

class CounterPage extends StatefulWidget {
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Widget Communication")),
      body: Center(
        child: Count(
          count: count,
          onCountSelected: () {
            print("Count was selected.");
          },
        )
      ),
    );
  }
}

编译您的代码并让它在模拟器中运行。 与按钮交互并观察控制台中的输出:

OutputCount was selected.

然而,此时 count 值将保持为零。

接下来,您将添加一个 Function(x)

第 4 步 — 使用 Function(x)

VoidCallback 对于没有预期值的回调事件很有用。 对于要将值返回给父级的场景,您将需要使用 Function(x)

重新访问 count.dart 并添加 Function(int) onCountChanged

lib/count.dart

import 'package:flutter/material.dart';

class Count extends StatelessWidget {
  final int count;
  final VoidCallback onCountSelected;
  final Function(int) onCountChanged;

  Count({
    @required this.count,
    @required this.onCountChanged,
    this.onCountSelected,
  });

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        IconButton(
          icon: Icon(Icons.add),
          onPressed: () {
            onCountChanged(1);
          },
        ),
        FlatButton(
          child: Text("$count"),
          onPressed: () => onCountSelected(),
        ),
        IconButton(
          icon: Icon(Icons.remove),
          onPressed: () {
            onCountChanged(-1);
          },
        ),
      ],
    );
  }
}

然后,重新访问 counter_page.dart 并监听 onCountChange 回调:

lib/counter_page.dart

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

class CounterPage extends StatefulWidget {
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Widget Communication")),
      body: Center(
        child: Count(
          count: count,
          onCountSelected: () {
            print("Count was selected.");
          },
          onCountChanged: (int val) {
            setState(() => count += val);
          },
        )
      ),
    );
  }
}

单击按钮时,更改值会从 Count 子控件传递到 CounterPage 父控件。 然后,执行valcount之间的加法并更新count

编译你的代码并让它在模拟器中运行:

Add (+) 和 Remove (-) 按钮交互,count 值应分别递增和递减。

结论

在本文中,您学习了如何使用 VoidCallbackFunction(x) 使用回调样式的事件在 Flutter 的小部件之间进行通信。

如果您想了解有关 Flutter 的更多信息,请查看 我们的 Flutter 主题页面 以获取练习和编程项目。