【Flutter 工程】005-代码分离实践:flutter_hooks & functional_widget
文章目录
- 【Flutter 工程】005-代码分离实践:flutter_hooks & functional_widget
- 一、概述
- 1、Flutter “嵌套地狱”
- 2、代码分离实践
- 二、实践
- 1、安装 flutter_hooks & functional_widget
- 2、代码示例
- 3、生成代码
- 命令
- 生成的代码
- 4、运行结果
一、概述
1、Flutter “嵌套地狱”
在Flutter开发中,“嵌套地狱”(Nesting Hell)是指在构建复杂的UI布局时,由于多层嵌套的组件结构,代码变得冗长、难以维护和理解的情况。
Flutter使用组件树的方式来构建用户界面,每个UI元素都是一个组件,可以包含其他组件。在某些情况下,特别是当需要实现复杂的布局或嵌套的组件结构时,代码中的组件嵌套层级可能会不断增加,从而导致出现”嵌套地狱”。
“嵌套地狱”可能会带来以下问题:
- 代码冗长和可读性差:过多的嵌套会导致代码变得冗长,难以理解和维护。每个嵌套层级都需要处理相应的组件和属性,使得代码结构复杂化。
- 性能问题:过多的嵌套可能会导致渲染性能下降。每个嵌套层级都需要进行布局计算和绘制操作,增加了渲染的负担。
- 调试和排查问题困难:当出现UI问题或错误时,由于嵌套层级较多,定位问题可能会变得更加困难。调试和排查错误所需的时间和精力也会增加。
为了避免”嵌套地狱”,可以考虑以下策略:
- 抽取可复用的组件:将复杂的UI部分拆分为独立的可复用组件,使代码更加模块化和清晰。这样可以减少嵌套层级,并使代码更易读和维护。
- 使用布局组件:Flutter提供了各种布局组件(如Row、Column、Stack等),可以帮助管理UI布局。合理使用这些布局组件可以减少嵌套层级,并简化布局代码。
- 使用状态管理工具:对于具有复杂交互和状态管理的应用,使用适当的状态管理工具(如Provider、Bloc等)可以减少嵌套层级,并更好地组织和管理应用的状态和逻辑。
- 审视UI设计和交互需求:在设计UI和交互时,尽量避免过于复杂和深层次的嵌套结构,简化UI布局和交互流程,以提高代码的可读性和维护性。
2、代码分离实践
结合 flutter_hooks & functional_widget 两个库实现代码分离。
参考文章:
【Flutter 工程】003-钩子函数:Flutter Hooks
https://blog.csdn.net/qq_29689343/article/details/130885106
【Flutter 工程】004-代码生成:functional_widget
https://blog.csdn.net/qq_29689343/article/details/130887815
用一种更有条理的方法写Flutter代码——使用Flutter Hooks与函数式组件
https://blog.csdn.net/qq_50101967/article/details/128688448
二、实践
1、安装 flutter_hooks & functional_widget
# 安装 flutter_hooksflutter pub add flutter_hooks# 安装 functional_widgetflutter pub add dev:functional_widget dev:build_runner functional_widget_annotation
2、代码示例
方法是否以
$
开头有自己决定!
import 'package:flutter/material.dart';import 'package:flutter_hooks/flutter_hooks.dart';import 'package:functional_widget_annotation/functional_widget_annotation.dart';part 'main.g.dart';void main() {runApp(const MyApp());}class MyApp extends StatelessWidget {const MyApp({super.key}); Widget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),useMaterial3: true,),home: const MyHomePage(title: 'Flutter Demo Home Page'),);}}/// 视图代码class MyHomePage extends HookWidget {const MyHomePage({super.key, required this.title});final String title; Widget build(BuildContext context) {final counter = Counter.use(0);return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(title),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[const $OnlyText('You have pushed the button this many times:'),$TextWithStyle('${counter.value}'),$AddButton(counter.inc),$DecButton(counter.dec),],),),);}}/// 逻辑代码class Counter {static use(initialValue) {return Counter().._count = useState(initialValue);}late final ValueNotifier<int> _count;get value => _count.value;inc() {_count.value++;}dec() {_count.value--;}}/// 样式代码 Widget $onlyText(String text) {return Text(text);} Widget $textWithStyle(BuildContext context, String text) {return Text(text,style: Theme.of(context).textTheme.headlineLarge,);} Widget $addButton(final VoidCallback? onPressed) {return FloatingActionButton(onPressed: onPressed,tooltip: 'Increment',child: const Icon(Icons.add),);} Widget $decButton(final VoidCallback? onPressed) {return FloatingActionButton(onPressed: onPressed,tooltip: 'Decrement',child: const Icon(Icons.minimize),);}
3、生成代码
命令
# --delete-conflicting-outputs 可选,会在生成代码冲突的时候,删除原来的代码,重新生成flutter pub run build_runner build --delete-conflicting-outputs
生成的代码
// GENERATED CODE - DO NOT MODIFY BY HANDpart of 'main.dart';// **************************************************************************// FunctionalWidgetGenerator// **************************************************************************/// 样式代码class $OnlyText extends StatelessWidget {/// 样式代码const $OnlyText(this.text, {Key? key,}) : super(key: key);/// 样式代码final String text; Widget build(BuildContext _context) => $onlyText(text);}class $TextWithStyle extends StatelessWidget {const $TextWithStyle(this.text, {Key? key,}) : super(key: key);final String text; Widget build(BuildContext _context) => $textWithStyle(_context,text,);}class $AddButton extends StatelessWidget {const $AddButton(this.onPressed, {Key? key,}) : super(key: key);final void Function()? onPressed; Widget build(BuildContext _context) => $addButton(onPressed);}class $DecButton extends StatelessWidget {const $DecButton(this.onPressed, {Key? key,}) : super(key: key);final void Function()? onPressed; Widget build(BuildContext _context) => $decButton(onPressed);}