首页
苏兮影视
随笔记
壁纸
更多
直播
时光轴
友联
关于
统计
Search
1
软件添加id功能按钮
708 阅读
2
v2ray节点搭建
508 阅读
3
typecho非常有特色的模块
460 阅读
4
QQxml消息卡片生成源码
421 阅读
5
Linux下提权常用小命令
366 阅读
谈天说地
建站源码
经验教程
资源分享
动漫美图
登录
Search
标签搜索
java
flutter
springboot
rust
安卓
linux
vue
docker
joe
快捷键
git
fish shell
maven
redis
netty
dart
groovy
js
设计模式
rpc
尽意
累计撰写
95
篇文章
累计收到
38
条评论
首页
栏目
谈天说地
建站源码
经验教程
资源分享
动漫美图
页面
苏兮影视
随笔记
壁纸
直播
时光轴
友联
关于
统计
搜索到
8
篇与
的结果
Flutter 状态管理之 Provider
在 Flutter 开发中,状态管理是一个非常重要的话题。而 Provider 作为 Flutter 社区推荐的状态管理解决方案之一,因其轻量、简单、灵活而备受欢迎。本文将系统地解析 Provider 的基本用法和高级用法,包括 read、watch、consume 和 selector,并通过单个 Model 和多个 Model 的管理案例详细说明。什么是 Provider?Provider 是一个基于 InheritedWidget 的封装,用于高效地管理 Flutter 应用中的状态。它的主要优势包括:简单易用,符合 Dart 语言的惯用写法。支持多层 Widget 树的状态共享。高性能,只会更新需要重建的 Widget。通过 Provider,我们可以方便地实现依赖注入和响应式编程。Provider 的基本用法在使用 Provider 之前,需要先在 pubspec.yaml 文件中添加依赖:dependencies: provider: ^lates以下通过一个简单的计数器示例说明 Provider 的基本用法。单个 Model 的使用创建 Model 类import 'package:flutter/foundation.dart'; class CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } }在应用中注册 Providerimport 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'counter_model.dart'; void main() { runApp( ChangeNotifierProvider( create: (_) => CounterModel(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: CounterScreen(), ); } }获取状态和更新 UIclass CounterScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Provider 示例')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('当前计数:'), Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), ), ); } }多个 Model 的管理在大型应用中,可能需要管理多个 Model。在这种情况下,可以使用 MultiProvider。定义多个 Modelclass CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } } class ThemeModel with ChangeNotifier { bool _isDark = false; bool get isDark => _isDark; void toggleTheme() { _isDark = !_isDark; notifyListeners(); } }注册多个 Providervoid main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => CounterModel()), ChangeNotifierProvider(create: (_) => ThemeModel()), ], child: MyApp(), ), ); }在不同的 Widget 中使用 Modelclass CounterScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Provider 示例'), actions: [ IconButton( icon: Icon(Icons.brightness_6), onPressed: () => context.read<ThemeModel>().toggleTheme(), ), ], ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('当前计数:'), Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), ), ); } }Provider 中的核心方法1. readread 方法用于访问状态,但不会订阅状态的变化。这意味着调用 read 的 Widget 在状态更新时不会重建。适用场景:需要触发一次性的操作,例如调用方法或事件处理器。FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), )2. watchwatch 方法会订阅状态的变化。当状态发生变化时,使用 watch 的 Widget 会重新构建。适用场景:需要根据状态动态更新 UI。Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, )3. consumeConsumer 是 Provider 提供的一个 Widget,能够订阅状态并重建自身及其子树。适用场景:需要精确控制重建的范围,避免不必要的 Widget 重建。Consumer<CounterModel>( builder: (context, counter, child) { return Text( counter.count.toString(), style: Theme.of(context).textTheme.headline4, ); }, )4. selectorSelector 提供了更高效的订阅方式,可以从状态中选择特定字段进行订阅,避免因其他字段变化导致的无效重建。适用场景:状态对象较大且只需要监听其中部分字段时。Selector<CounterModel, int>( selector: (_, counter) => counter.count, builder: (context, count, child) { return Text( count.toString(), style: Theme.of(context).textTheme.headline4, ); }, )性能优化建议使用 Consumer 或 Selector 控制重建范围:避免不必要的父级 Widget 重建。分离逻辑和 UI:将业务逻辑放在模型中,UI 层只负责展示。尽量减少依赖注入的深度:如果可能,使用多层 Provider。
2024年12月06日
11 阅读
0 评论
1 点赞
flutter开发桌面应用实现窗体透明
2024年09月21日
48 阅读
0 评论
1 点赞
2024-09-21
1.使用bitsdojo_window插件:使用命令添加dart pub add bitsdojo_window2.在 windows/runner/main.cpp 中进行窗口透明设置:#include <flutter/dart_project.h> #include <flutter/flutter_view_controller.h> #include <windows.h> #include "flutter_window.h" #include "utils.h" // 添加的代码 #include<bitsdojo_window_windows/bitsdojo_window_plugin.h> auto bdw = bitsdojo_window_configure(BDW_CUSTOM_FRAME | BDW_HIDE_ON_STARTUP); void EnableTransparency(HWND hwnd) { SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); COLORREF colorKey = RGB(255, 255, 255); BYTE alpha = 128; // 设置透明度(0-256) SetLayeredWindowAttributes(hwnd, colorKey, alpha, LWA_ALPHA); } // 到这里结束 int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, _In_ wchar_t *command_line, _In_ int show_command) { // Attach to console when present (e.g., 'flutter run') or create a // new console when running with a debugger. //...省略中间的代码 // 添加的代码 EnableTransparency(window.GetHandle()); // 到这里结束 window.SetQuitOnClose(true); ::MSG msg; while (::GetMessage(&msg, nullptr, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } ::CoUninitialize(); return EXIT_SUCCESS; } 3.设置页面背景为透明:Scaffold( backgroundColor: Colors.transparent, body: Container() )4.实现的效果:
2024-05-17
记录一下flutter的值传递细节
最近在实现一个类似qq相册的功能,点击右上角图片的小圆圈框选。思路也很简单,当image控件的值发送改变时,重新rebuild渲染,当然是局部渲染,所以要封装这么一个控件,构造函数: final File file; final BottomImageChanged isChanged; final VoidCallback onPress; 图片显示使用的FileImage,传递一个回调函数,用来处理区选对应的widget,由于dart的传参对于基本变量都是值传递吗,所以也就造成了父控件值改变了,但是子组件不能监听到,所以使用类包装一下基础变量值,提供get set方法。也可以使用ValueNotifier包装基础变量,List.filled 和 List.generate 都是用于创建固定长度的列表List.filled:列表中的所有元素都是相同的对象,适用于需要多个相同对象引用的情况。List.generate:每个元素都是独立的对象,适用于需要为每个列表项创建不同对象的情况,例如为每个列表项创建独立的 ValueNotifier。
2024年05月17日
31 阅读
0 评论
0 点赞
flutter 卡在 "Running Gradle task..."
每次启用新的flutter插件都会卡一阵子,网上的说法也都是换maven下载源,即使是换了也还是会卡住。解决方案:在终端中打开flutter项目目录,cd到android目录下,使用gradlew clean清理一下,清理完成后重新build即可。
2024年05月11日
29 阅读
0 评论
1 点赞
2024-05-02
flutter实现封装控制器
在flutter中,尽管已经可以通过状态提升实现小部分的值传递,用回调函数的方法去修改父类的值,在父类调用setstate相当于重新rebuild了父类以及子组件的全部组件,而我们只需要看到子组件的内容发送改变,对此性能上无疑是浪费的。所以需要对组件进行封装,使每次更新只涉及到需要的子组件,这也是性能优化以及解耦的一种解决方案。新建一个controller类继承ChangeNotifier私有化成员变量,设置get set方法,set数据的时候调用notifyListeners函数,通知框架需要更新到新的数据通过ListenableBuilder组件监听需要更新的ChangeNotifier对象每次数据更新使调用set方法都会调用notifyListeners函数,在listenable又会监听到数据的改变,从而进行重绘。
2024年05月02日
40 阅读
0 评论
1 点赞
1
2