【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元素都是一个组件,可以包含其他组件。在某些情况下,特别是当需要实现复杂的布局或嵌套的组件结构时,代码中的组件嵌套层级可能会不断增加,从而导致出现”嵌套地狱”。

“嵌套地狱”可能会带来以下问题:

  1. 代码冗长和可读性差:过多的嵌套会导致代码变得冗长,难以理解和维护。每个嵌套层级都需要处理相应的组件和属性,使得代码结构复杂化。
  2. 性能问题:过多的嵌套可能会导致渲染性能下降。每个嵌套层级都需要进行布局计算和绘制操作,增加了渲染的负担。
  3. 调试和排查问题困难:当出现UI问题或错误时,由于嵌套层级较多,定位问题可能会变得更加困难。调试和排查错误所需的时间和精力也会增加。

为了避免”嵌套地狱”,可以考虑以下策略:

  1. 抽取可复用的组件:将复杂的UI部分拆分为独立的可复用组件,使代码更加模块化和清晰。这样可以减少嵌套层级,并使代码更易读和维护。
  2. 使用布局组件:Flutter提供了各种布局组件(如Row、Column、Stack等),可以帮助管理UI布局。合理使用这些布局组件可以减少嵌套层级,并简化布局代码。
  3. 使用状态管理工具:对于具有复杂交互和状态管理的应用,使用适当的状态管理工具(如Provider、Bloc等)可以减少嵌套层级,并更好地组织和管理应用的状态和逻辑。
  4. 审视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);}

4、运行结果