今天会讲下 inheritedWidget 组件,InheritedWidget 是 Flutter 中非常重要和强大的一种 Widget,它可以使 Widget 树中的祖先 Widget 共享数据给它们的后代 Widget,从而简化了状态管理和数据传递的复杂性,提高了代码的可读性、可维护性和性能。
Provider 就是对 inheritedWidget 的高度封装
Flutter_bloc 也是这样
Flutter_bloc 中确实有 provider 的引用
如果你只是想简单的状态管理几个全局数据,完全可以轻巧的使用 inheritedWidget 。
今天就来讲下如何使用和要注意的地方。
https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html
在 Flutter 中,状态管理是指管理应用程序的数据和状态的方法。在应用程序中,有许多不同的组件和部件,它们可能需要在不同的时间点使用相同的数据。状态管理的目的是使这些数据易于访问和共享,并确保应用程序的不同部分保持同步。
在 Flutter 中,有不同的状态管理方法可供选择,包括:
lib/states/user_profile.dart
// 用户登录信息 class UserProfileState extends InheritedWidget { ... }
参数
const UserProfileState({ super.key, required this.userName, required this.changeUserName, required Widget child, // 包含的子节点 }) : super(child: child); /// 用户名 final String userName; /// 修改用户名 final Function changeUserName;
of 方法查询,依据上下文 context
static UserProfileState? of(BuildContext context) { final userProfile = context.dependOnInheritedWidgetOfExactType<UserProfileState>(); // 安全检查 assert(userProfile != null, 'No UserProfileState found in context'); return userProfile; }
需要做一个 userProfile 空安全检查
重写 updateShouldNotify 通知更新规则
bool updateShouldNotify(UserProfileState oldWidget) { return userName != oldWidget.userName; }
如果用户名发生改变进行通知
lib/widgets/header.dart
class HeaderWidget extends StatelessWidget { const HeaderWidget({super.key}); Widget build(BuildContext context) { String? userName = UserProfileState.of(context)?.userName; return Container( width: double.infinity, decoration: BoxDecoration( border: Border.all(color: Colors.blue), ), child: Text('登录:$userName'), ); } }
通过 String? userName = UserProfileState.of(context)?.userName; 的方式
读取状态数据 userName
lib/widgets/bottom.dart
class BottomWidget extends StatelessWidget { const BottomWidget({super.key}); Widget build(BuildContext context) { String? userName = UserProfileState.of(context)?.userName; return Container( width: double.infinity, decoration: BoxDecoration( border: Border.all(color: Colors.blue), ), child: Text('登录:$userName'), ); } }
lib/widgets/user_view.dart
class UserView extends StatefulWidget { const UserView({super.key}); State<UserView> createState() => _UserViewState(); } class _UserViewState extends State<UserView> { ...
成员变量
class _UserViewState extends State<UserView> { String? _userName;
重新 didChangeDependencies 依赖函数更新数据
void didChangeDependencies() { _userName = UserProfileState.of(context)?.userName; super.didChangeDependencies(); }
通过 UserProfileState.of(context)?.userName; 的方式读取
build 函数
Widget build(BuildContext context) { return Container( width: double.infinity, decoration: BoxDecoration( border: Border.all(color: Colors.purple), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('用户名:$_userName'), ElevatedButton( onPressed: () { // 随机 10 个字母 String randomString = String.fromCharCodes( List.generate( 10, (index) => 97 + Random().nextInt(26), ), ); // 改变用户名 UserProfileState.of(context)?.changeUserName(randomString); }, child: const Text('改变名称'), ), ], ), ); }
randomString 是一个随机的 10 个字母
通过 UserProfileState.of(context)?.changeUserName(randomString); 的方式触发函数,进行状态更改。
lib/page.dart
class AppPage extends StatefulWidget { const AppPage({super.key}); State<AppPage> createState() => _AppPageState(); } class _AppPageState extends State<AppPage> { ...
成员变量
class _AppPageState extends State<AppPage> { String _userName = '未登录';
给了一个 未登录 的默认值
修改用户名函数
// 修改用户名 void _changeUserName(String userName) { setState(() { _userName = userName; }); }
build 函数
Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('InheritedWidget'), ), body: UserProfileState( userName: _userName, changeUserName: _changeUserName, child: SafeArea( child: Column( children: const [ // 头部 HeaderWidget(), // 正文 Expanded(child: UserView()), // 底部 BottomWidget(), ], ), ), ), ); }
可以发现 UserProfileState 被套在了最外层,当然还有 Scaffold 。
包裹的子组件有:HeaderWidget、BottomWidget、UserView
状态过程如下:
- UserView 触发 _changeUserName 修改用户名
- _userName 改变的数据压入 UserProfileState
- UserProfileState 触发 updateShouldNotify
- 组件 didChangeDependencies 被触发
- 最后子成员组件更新成功
https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_inherited_widget
在 Flutter 中,InheritedWidget 是一种特殊的 Widget,它允许 Widget 树中的祖先 Widget 共享数据给它们的后代 Widget,而无需通过回调或参数传递数据。下面是 InheritedWidget 的一些主要作用和好处:
感谢阅读本文
如果我有什么错?请在评论中让我知道。我很乐意改进。
© 猫哥 ducafecat.com
end
Copyright 2023 ducafecat. All rights reserved.
微信: ducafecat, line: ducafecat,京ICP备2021009050号-3