【Flutter 工程】005-代码分离实践:flutter_hooks & functional_widget

  • Post author:
  • Post category:其他




【Flutter 工程】005-代码分离实践:flutter_hooks & functional_widget



一、概述



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_hooks
flutter pub add flutter_hooks

# 安装 functional_widget
flutter 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 HAND

part 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、运行结果

image-20230526160133811



版权声明:本文为qq_29689343原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。