Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Flutter组件传值

这篇文章一次讲清Flutter组件之间如何传值

作者:我叫柱子哥

这篇文章主要介绍了Flutter组件之间如何传值的相关资料,需要的朋友可以参考下

前言

在 Flutter 中,组件(Widget)之间的通信和数据传递是构建复杂 UI 的基础。  无论是父组件向子组件传值,还是兄弟组件之间通信,都有多种方式可以实现。  

本文将带你系统梳理 Flutter 中常见的几种组件传值方式,并提供对应示例代码。

1.不使用三方库

1.父组件向子组件传值(构造函数)

当我们需要集成子组件的时候,可以使用构造函数传值。

这是最基础、最常见的传值方式。

例如我们有一个子组件,代码如下:

class ChildWidget extends StatelessWidget {
  final String title;

  const ChildWidget({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

当我们集成这个子组件的时候,使用下面代码即可:

class _TransferToSonPageDemosState extends State<TransferToSonPageDemos> {
  void _goToTransferPage(){

  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text("父组件向子组件传值"),
      ),
      body: Center(
        child: ChildWidget(title: "Hello 子组件"),
      ),
    );
  }
}

2.子组件向父组件传值(回调函数)

例如在下面下面的实例中,点击子组件按钮的时候,当前组件显示子组件的值。

图1.子组件向父组件传值

我们可以设计一个子组件回到函数,这里以字符串为例,点击按钮的时候,随机生成个英文字母:

class ChildWidget extends StatelessWidget {
  final void Function(String)? onSend;

  const ChildWidget({super.key, this.onSend});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        final randomString = WordPair.random().asPascalCase;
        onSend?.call("子组件发送数据: $randomString");
      },
      child: Text("点击发送"),
    );
  }
}

然后我们在子类组件的回调函数中获取子组件的值,然后更新当前组件的状态。

class _TransferToFatherPageDemosState extends State<TransferToFatherPageDemos> {
  String receivedData = '';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text("子组件向父组件传值"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ChildWidget(onSend: (data) {
              setState(() {
                receivedData = data;
              });
            }),
            const SizedBox(height: 20),
            Text(
              receivedData,
              style: const TextStyle(fontSize: 16),
            ),
          ],
        ),
      ),
    );
  }
}

3.跨组件传值(InheritedWidget)

InheritedWidget是一种高效的数据共享方式,适用于在Widget树中跨层级传递数据。通过InheritedWidget,子组件可以轻松访问父组件提供的数据。

以下面UI为例,我们在有三个子页面,三个页面共享一个值。

图2.跨页面传值实例

在使用InheritedWidget的时候,首先设计下共享的数据,然后把InheritedWidget包括子组件即可。

class MyInheritedWidget extends InheritedWidget {
  final String data;

  MyInheritedWidget({required this.data, required Widget child}) : super(child: child);

  @override
  bool updateShouldNotify(MyInheritedWidget oldWidget) => data != oldWidget.data;

  static MyInheritedWidget? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
  }
}

在图2的实例中,我们通过下面的代码获取共享的数据:

class SecondPage extends StatelessWidget {
  final String sharedData;
  const SecondPage({super.key, required this.sharedData});

  @override
  Widget build(BuildContext context) {
    final data = sharedData;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("第二页"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '第二页读取到数据: $data',
              style: const TextStyle(fontSize: 18),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              child: const Text("跳转到第三页"),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (_) => ThirdPage(sharedData: data)),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

当然如果需要再整个app中共享某个数据,我们可以把它包裹到MaterialApp的外面。

4.GlobalKey

在 Flutter 中,GlobalKey 是一种强大的机制,允许你在组件树中跨组件访问某个 Widget 的 State、context 或 RenderObject,它不仅用于传值,还可以直接调用子组件方法或获取状态。这是构建组件通信的一种原生方式,不需要任何三方库。

1.你的场景结构

final GlobalKey<_MyCounterWidgetState> _childKey = GlobalKey();

你定义了一个 GlobalKey,类型是子组件 MyCounterWidget 的状态类 _MyCounterWidgetState。这意味着你可以在父组件中直接操作这个子组件的状态,实现:

✅ 父组件 → 子组件:调用方法 / 修改状态

(不推荐反向使用,即子组件操作父组件)

2.GlobalKey 实现传值的关键点

1.在父组件中声明 GlobalKey

final GlobalKey<_MyCounterWidgetState> _childKey = GlobalKey();

2.将这个 key 传递给子组件

MyCounterWidget(key: _childKey)

3.在父组件中调用子组件的状态方法

_childKey.currentState?.increment();

currentState 访问的是 MyCounterWidget 的状态对象 _MyCounterWidgetState,你可以像调用普通方法一样去触发状态变化或读写值。

4.示例代码

以下面代码为例,我们在当前Widget终端爱用子类Widget计时器:        

图3.GlobalKey用法

你定义了一个计数器子组件:

class _MyCounterWidgetState extends State<MyCounterWidget> {
  int _count = 0;

  void increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text('子组件计数:$_count', style: const TextStyle(fontSize: 18));
  }
}

然后在父组件中,通过下面的代码获取定时器Widget.

final GlobalKey<_MyCounterWidgetState> _childKey = GlobalKey();

然后就可以在代码中调用子组件的方法,完整实例如下:

import 'package:flutter/material.dart';
// GlobalKey Demo 页面
class GlobalKeyDemoPage extends StatefulWidget {
  const GlobalKeyDemoPage({super.key});

  @override
  State<GlobalKeyDemoPage> createState() => _GlobalKeyDemoPageState();
}

class _GlobalKeyDemoPageState extends State<GlobalKeyDemoPage> {
  final GlobalKey<_MyCounterWidgetState> _childKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GlobalKey 跨组件调用示例')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(child: MyCounterWidget(key: _childKey)),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              _childKey.currentState?.increment();
            },
            child: const Text('父组件调用子组件 +1'),
          ),
        ],
      ),
    );
  }
}

class MyCounterWidget extends StatefulWidget {
  const MyCounterWidget({super.key});

  @override
  State<MyCounterWidget> createState() => _MyCounterWidgetState();
}

class _MyCounterWidgetState extends State<MyCounterWidget> {
  int _count = 0;

  void increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text('子组件计数:$_count', style: const TextStyle(fontSize: 18));
  }
}

5.Navigator + pop返回值(页面返回传值)

用于页面跳转之后回传数据给前一个页面。

这是最基础的用法了,这里就不详细讲解了。

// 第二页中
Navigator.pop(context, "返回的数据");

// 第一个页面中
final result = await Navigator.push(...);
print("收到结果: $result");

6.单例类 / 静态变量(全局数据共享)

虽然不推荐频繁使用,但对于小量全局配置或临时缓存,可以使用:

class GlobalData {
  static String token = '';
}

2.使用状态管理类

在 Flutter 中,组件(Widget)之间的传值除了官方原生方式(如构造函数、InheritedWidget、GlobalKey)之外,还有多个非常流行的第三方库,它们提供了更清晰、更灵活、更强大的状态管理与传值机制,尤其适用于中大型项目。

下面是一些主流的三方库及其特点:

1. Provider(Google 推荐)

简洁、轻量,是官方团队推荐的状态管理库,基于 InheritedWidget 的封装。

📌 文档:https://pub.dev/packages/provider

2. Riverpod(Provider 的升级版)

Provider 作者主导开发的下一代状态管理库,更强大、更灵活,支持可组合性、无 BuildContext 限制。

📌 文档:https://riverpod.dev/

3. GetX

极简主义,语法直白,适用于快速开发与中小项目。

📌 文档:https://pub.dev/packages/get

4. Bloc / Cubit(Google 团队支持)

响应式 + 流(Stream)驱动的状态管理方式,适用于中大型项目,逻辑集中、可测试。

📌 文档:https://bloclibrary.dev

5. flutter_hooks

将 React 风格的“函数组件 + Hook”引入 Flutter,提高代码复用性和可读性。

📌 文档:https://pub.dev/packages/flutter_hooks

这几个库的需求场景对比如下:

需求场景

推荐库

特点说明

简单传值 / 局部状态

Provider

简洁稳定,入门推荐

跨页面全局状态 / 无 context

Riverpod

类型安全、无需 context,适合中大型

快速开发 + 响应式

GetX

语法直观、依赖注入方便

大型项目 / 状态严格受控

Bloc / Cubit

分层清晰,可测试性强

Hook 风格状态管理

flutter_hooks

代码优雅,便于复用

总结 

到此这篇关于Flutter组件之间如何传值的文章就介绍到这了,更多相关Flutter组件传值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文