【Flutter 工程】003-钩子函数:Flutter Hooks

news2024/12/31 22:29:47

【Flutter 工程】003-钩子函数:Flutter Hooks

文章目录

  • 【Flutter 工程】003-钩子函数:Flutter Hooks
  • 一、概述
    • 1、前言
    • 2、Flutter Hooks 概述
  • 二、`useState` 基本使用
    • 0、计数器官方 demo
    • 1、安装 flutter_hooks
    • 2、代码改造
    • 3、运行结果
    • 4、神奇的事情
  • 三、使用 `HookBuilder` 实现更小范围的组件更新
    • 1、简单分析
    • 2、使用 `HookBuilder` 实现更小范围的组件更新
      • 代码改造
      • 运行结果
      • 控制台

一、概述

1、前言

Hooks 是 React 框架中引入的一项特性,用来分离状态逻辑和视图逻辑。如今,这个概念已经不仅限于 React,其他前端框架也在学习和借鉴。在 Flutter 开发中,业务逻辑和视图逻辑的耦合一直是一个比较突出的痛点,这也是各大前端框架常遇到的一个共性难题。为了解决这个问题,前端社区提出了许多方案,如MVP、MVVM、React 的Mixin、高阶组件(HOC),以及Hooks。在Flutter中,开发者可能对Mixin比较熟悉。但是,Mixin的应用也存在一定的局限性:

  • Mixin 之间可能互相依赖,导致依赖关系混乱;
  • Mixin 之间可能产生冲突,难以识别和解决;
  • Mixin的可复用性有限,不利于组件解耦。

基于此,本文将介绍 Hooks 的概念和应用,看是否能够避免 Mixin 的这些限制,实现更好的状态逻辑和视图逻辑的解耦。Hooks 为我们提供了一种无需修改组件结构的方式来复用状态逻辑。我们可以通过 Hooks 将复杂的状态逻辑抽离出来,这有助于提高组件的内聚性,实现高度可复用的状态逻辑。

2、Flutter Hooks 概述

Flutter Hooks是一个用于 Flutter 应用程序的第三方包,它提供了一种优雅且方便的方式来管理 Flutter 小部件的状态和生命周期

在Flutter中,通常使用 StatefulWidget 来管理具有可变状态的小部件。然而,使用 StatefulWidget 可能会导致代码冗长,因为需要创建一个单独的State类来管理状态,并且需要在小部件和状态之间进行额外的通信

Flutter Hooks通过使用钩子(hooks)的概念,提供了一种更简洁的方式来管理小部件的状态。钩子是一些函数,可以在小部件函数内部调用,它们提供了一种轻量级的状态管理机制。

使用Flutter Hooks,您可以在无需创建 StatefulWidget 的情况下管理状态。它提供了一些常用的钩子函数,例如useState(用于管理状态)、useEffect(用于处理生命周期)、useMemo(用于记忆计算结果)和useCallback(用于记忆回调函数)。这些钩子函数使得管理小部件的状态和副作用变得更加简单和直观。

除了内置的钩子函数,Flutter Hooks还提供了自定义钩子函数的能力,以便您可以根据应用程序的需求创建自己的钩子。

总的来说,Flutter Hooks是一个强大而灵活的库,可以帮助开发者更好地组织和管理Flutter应用程序中的小部件状态和生命周期。它可以提高代码的可读性和可维护性,并且减少了使用传统的 StatefulWidget 时的样板代码量。

二、useState 基本使用

0、计数器官方 demo

去掉了注释!

import 'package:flutter/material.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 StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

1、安装 flutter_hooks

flutter pub add flutter_hooks

2、代码改造

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.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'),
    );
  }
}

// 关注:继承自 HookWidget
class MyHomePage extends HookWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  Widget build(BuildContext context) {
    // 关注:使用 useState
    final counter = useState(0);
    print("执行时间:" + DateTime.now().toString() + "  counter.value = " + counter.value.toString());
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            // 关注:使用 counter.value
            Text(
              '${counter.value}',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        // 关注:使用 counter.value ++
        onPressed: () => counter.value++,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

3、运行结果

image-20230526130958068

4、神奇的事情

hook 的实现原理这里暂不探讨,可参考文章:https://juejin.cn/post/7220295071060541495

  • counter 的值更新了,也重新执行了 build 方法,但是 counter 变量的值并没有被重新初始化,而是实现了复用!

    Syncing files to device Windows...
    flutter: 执行时间:2023-05-26 13:14:56.030115  counter.value = 14
    Reloaded 1 of 668 libraries in 168ms (compile: 23 ms, reload: 62 ms, reassemble: 49 ms).
    flutter: 执行时间:2023-05-26 13:15:12.404470  counter.value = 15
    
  • 没有 State 代码,HookWidget 是继承 StatelessWidget

    abstract class HookWidget extends StatelessWidget {
     /// Initializes [key] for subclasses.
     const HookWidget({Key? key}) : super(key: key);
    
     
     _StatelessHookElement createElement() => _StatelessHookElement(this);
    }
    

三、使用 HookBuilder 实现更小范围的组件更新

1、简单分析

上述示例中,发生变化的仅仅是 count 的值,需要更新的也只是一个 Text 组件的文本,但由于 count 的值的更新却导致整个页面的重建,这是不合理的!

传统的解决方案是将 Text 单独封装,但这徒增了很多代码!flutter_hooks 提供了 HookBuilder 来实现这个需求!

2、使用 HookBuilder 实现更小范围的组件更新

代码改造

这里做一个简单示例来展示基本用法,不纠结极客风格的代码!

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.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'),
    );
  }
}

// 关注:继承自 HookWidget
class MyHomePage extends HookWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  Widget build(BuildContext context) {
    print("外层 build 执行时间:" + DateTime.now().toString());
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      // 关注:使用 HookBuilder
      body: HookBuilder(
        builder: (context) {
          print("内层 build 执行时间:" + DateTime.now().toString());
          final counter = useState(0);
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                // 关注:使用 counter.value
                Text(
                  '${counter.value}',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
                FloatingActionButton(
                  // 关注:使用 counter.value ++
                  onPressed: () => counter.value++,
                  tooltip: 'Increment',
                  child: const Icon(Icons.add),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

运行结果

image-20230526134057742

控制台

Syncing files to device Windows...
flutter: 外层 build 执行时间:2023-05-26 13:40:46.152943
flutter: 内层 build 执行时间:2023-05-26 13:40:46.182019
flutter: 内层 build 执行时间:2023-05-26 13:40:49.101309
flutter: 内层 build 执行时间:2023-05-26 13:40:49.297099
flutter: 内层 build 执行时间:2023-05-26 13:40:49.644307

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/571654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个合格的IT信息化公司需要具备哪些资质?

今天智达鑫业小编给大家汇总下目前信息化企业具有的一些常见资质证书有哪些&#xff0c; 正规IT企业应具备以下资质&#xff0c;具有的资格以及与此资格相适应的质量等级标准。专业的it企业资质包括经营资质四项资质、能力资质六项资质 1、it企业资质经营资质 【双软企业认定…

常用监控方案 Prometheus + Grafana 简单使用小结

文章目录 前言一、概念1.1 发展1.2 时序数据1.3 Metric 二、Prometheus2.1 架构2.2 配置2.3 查询语言PromQL2.4 Exporter 三、Grafana3.1 数据源3.2 权限3.3 面板可视化3.4 仪表盘 四、实战4.1 监控 Windows/Linux4.2 监控 JVM4.3 监控 MySQL4.4 监控 Springboot API 参考 前言…

拿森Onebox 2.0新品发布,已获多家车企定点,明年出货量将达百万台

近日&#xff0c;拿森科技在上海举办了2023年新品发布会&#xff0c;重磅发布了拿森Onebox 2.0集成式智能制动系统&#xff08;NBC&#xff09;。 该产品采用全解耦式制动技术&#xff0c;集成了行车制动、驻车制动、车辆稳定性控制等全部功能&#xff0c;包括协调式能量回收、…

Springboot中使用mail邮件

Springboot中使用mail邮件发送 1、配置邮箱的POP3/SMTP服务和IMAP/SMTP服务2、导入依赖和一些默认#配置新的3、发送邮件4、整合工具类 1、配置邮箱的POP3/SMTP服务和IMAP/SMTP服务 这里使用的是QQ邮箱,进入设置-账户&#xff0c;开启下服务。 开启后获取授权码&#xff0c;保存…

华秋DFM软件迭代升级,让用户拥有更好的体验

华秋DFM软件在不断改进和升级的过程中&#xff0c;积极收集和了解用户的需求和反馈&#xff0c;不断提高软件的功能实用性和用户体验。在本次软件迭代中&#xff0c;华秋DFM软件针对以下功能点进行了优化和改进&#xff0c;以让操作更加便捷、让用户拥有更好的体验&#xff01;…

365天深度学习打卡 第P9周:YOLOv5的backbone实现

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 文章目录 一、Backbone模块代码1.1 Conv模块1.2 C3模块Bottleneck模块SPPF模块 二、数据集和相关参数设置2.1 数据集操作2.2 相关参数设置2.3…

chatgpt赋能python:Python修改密码:一种安全可靠、快速高效的方式

Python 修改密码&#xff1a;一种安全可靠、快速高效的方式 在数字化时代&#xff0c;越来越多的信息被存储在计算机系统中&#xff0c;因此密码的保护变得尤为重要。人们需要保证他们的密码是安全可靠的&#xff0c;并定期更换密码。Python作为一种强大而且通用的编程语言&am…

Unity用鼠标拖拽UI,UI跟随鼠标移动

Unity用鼠标拖拽UI&#xff0c;UI跟随鼠标移动 效果一、原理二、源码总结&#x1f4a2;&#x1f4a2;版权声明 效果 先上效果 一、原理 继承几个拖拽的接口 IBeginDragHandler, IDragHandler,IEndDragHandler 计算下偏移量&#xff0c;转换下坐标系 限制下可拖拽的范围&…

Tensorflow2基础代码实战系列之时间序列预测任务

深度学习框架Tensorflow2系列 注&#xff1a;大家觉得博客好的话&#xff0c;别忘了点赞收藏呀&#xff0c;本人每周都会更新关于人工智能和大数据相关的内容&#xff0c;内容多为原创&#xff0c;Python Java Scala SQL 代码&#xff0c;CV NLP 推荐系统等&#xff0c;Spark …

实时时钟 RTC

概述 实时时钟(RTC) 模块可长时间维持精确计时&#xff0c;为系统提供实时时钟和日历。该模块功耗极低&#xff0c;最大程度延长电池寿命。 RTC的主要特点&#xff1a; ⚫ BCD 时间 格式 &#xff0c;完整万年历 ⚫ 支持数字调校&#xff0c; 最高 精度可达 0. 06 ppm ⚫ 可输出…

作为996社畜,如何自学Python?一文讲清楚

作为996社畜&#xff0c;应该如何自学Python&#xff1f;今天就给大家分享一下&#xff0c;工作之余&#xff0c;应该如何学习Python&#xff1f; 1. 明确目标 对于零基础的学员而言&#xff0c;要明确你学习Python仅仅是为了满足好奇心&#xff1f;还是有工作需要&#xff0c…

如何使用ArcGIS制作气温空间分布图

本文使用ArcMap10.2&#xff0c;以湖北省为例&#xff0c;通过空间插值&#xff0c;制作湖北省1981-2010年20年平均气温空间分布图 树谷资料库资源大全 1 数据准备 可在中国气象数据网下载湖北省1981-2010共20年的各区站累年平均气温数据和各区站经纬度数据。打开为txt格式 在…

【三】设计模式~~~创建型模式~~~抽象工厂模式(Java)

【学习难度&#xff1a;★★★★☆&#xff0c;使用频率&#xff1a;★★★★★】 3.1. 模式动机 在工厂方法模式中具体工厂负责生产具体的产品&#xff0c;每一个具体工厂对应一种具体产品&#xff0c;工厂方法也具有唯一性&#xff0c;一般情况下&#xff0c;一个具体工厂中…

【计算机网络】网络基础(一)

首先声明&#xff1a;这是开发中用到的网络的知识点&#xff0c;侧重点在于编程实践&#xff0c;不重视概念。网络基础不在于细节&#xff0c;在于构建宏观的结构。后面重点在于网络套接字编程&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 目录 1.背景知识 …

经典文献阅读之--ERASOR(栅格占用过滤动态障碍物)

0. 简介 之前作者在《激光雷达动态障碍物滤除-调研与展望》以及《3D帧间匹配-----剔除动态障碍物》中提到了如何通过各种方法来完成动态障碍物的滤波。而本文也将围绕着如何完成动态障碍物滤波来展开&#xff0c;来介绍《ERASOR: Egocentric Ratio of Pseudo Occupancy-based …

CentOS系统如何开展爬虫工作

CentOS 系统可以用于进行爬虫工作。实际上&#xff0c;很多大型网站和在线服务都运行在 Linux 系统下&#xff0c;包括 CentOS、Ubuntu、Debian 等&#xff0c;因此 CentOS 系统也常用于进行爬虫工作。 在CentOS系统上开展爬虫工作&#xff0c;可以按照以下步骤进行&#xff1a…

CESSCN安全设计与集成一级-中国通信企业协会通信网络安全服务能力评定证书

通信网络安全设计与集成服务能力评定是依据《通信网络安全防护管理办法》、《电信网与互联网第三方安全服务评定准则》YD/T2669-2013、以及《通信网络安全服务能力评定管理办法》的具体要求&#xff0c;对通信网络安全服务单位的技术能力、服务能力、质量保证能力、人员构成与素…

智能路由器开发之OpenWrt简介

智能路由器开发之OpenWrt简介 1. 引言 1.1 智能路由器的重要性和应用场景 智能路由器作为网络通信的核心设备&#xff0c;具有重要的地位和广泛的应用场景。传统的路由器主要提供基本的网络连接功能&#xff0c;但随着智能家居、物联网和大数据应用的快速发展&#xff0c;对于…

池州控股集团财务共享项目启动啦!

近日&#xff0c;由用友网络承建的池州市投资控股集团有限公司财务共享项目启动会成功举办&#xff0c;也标志着池州控股集团财务共享项目正式启动&#xff01;池州控股集团总经理刘俊、用友国资事业部总经理汪发清及其他相关专家和项目组主要成员参加了此次启动会。 池州投控集…

100种思维模型之全局观思维模型-67

全局观思维模型&#xff0c;一个教我们由点到线&#xff0c;由线到面&#xff0c;再由面到体&#xff0c;不断的放大格局去思考问题的思维模型。 01、何谓全局观思维模型 一、全局观思维 什么叫全局观&#xff1f; 世界上的所有东西&#xff0c;都是被规律作用者的&#xff0c…