Flutter Riverpod 使用详细解析
📚 Flutter 状态管理系列文章目录
-
Flutter 状态管理(setState、InheritedWidget、 Provider 、Riverpod、 BLoC / Cubit、 GetX 、MobX 、Redux)
-
setState() 使用详解:原理及注意事项
-
InheritedWidget 组件使用及原理
-
Flutter 中 Provider 的使用、注意事项与原理解析(含代码实战)
-
GetX 用法详细解析以及注意事项
-
Flutter BLoC 使用详细解析
-
Flutter MobX 响应式原理与实战详解
-
Flutter Riverpod 使用详细解析
-
Riverpod原理解析(实现一个自己的Riverpod
源码地址
📌 Riverpod 是 Flutter 官方推荐的状态管理方案之一,相比 Provider 更灵活、安全、支持组合、异步、热重载、IDE 类型推导。
📁 1. 安装依赖
在 pubspec.yaml
添加:
dependencies:flutter_riverpod: ^2.5.1
然后执行:
flutter pub get
🧠 2. 核心概念简述
类型 | 描述 | 示例用途 |
---|---|---|
Provider | 只读数据 | 常量、服务类 |
StateProvider | 原始值的可变状态(int/bool) | 计数器、开关 |
StateNotifierProvider | 复杂对象状态 + 控制逻辑 | 列表、对象、业务逻辑 |
ChangeNotifierProvider | ChangeNotifier 封装的旧模式 | 第三方 SDK 封装 |
FutureProvider | 异步加载 | 网络请求、初始化数据 |
StreamProvider | 实时数据流 | WebSocket、定时器 |
🧪 3. 实战代码讲解
示例场景:Todo 应用
✅ Provider
:静态或只读依赖
final greetingProvider = Provider<String>((ref) {return "Hello, Riverpod!";
});class GreetingWidget extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final greeting = ref.watch(greetingProvider);return Text(greeting);}
}
💡 用于配置、单例、不可变依赖。
✅ StateProvider
:简单状态(如 int、bool)
final counterProvider = StateProvider<int>((ref) => 0);class CounterPage extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final count = ref.watch(counterProvider);return Column(children: [Text('Count: $count'),ElevatedButton(onPressed: () => ref.read(counterProvider.notifier).state++,child: Text('Increment'),),],);}
}
💡 简单值状态管理的首选。
✅ StateNotifierProvider
:结构化业务逻辑
定义模型:
class Todo {final String id;final String title;Todo({required this.id, required this.title});
}
定义状态控制器:
class TodoNotifier extends StateNotifier<List<Todo>> {TodoNotifier() : super([]);void add(String title) {final todo = Todo(id: DateTime.now().toIso8601String(), title: title);state = [...state, todo];}void remove(String id) {state = state.where((t) => t.id != id).toList();}
}final todoListProvider =StateNotifierProvider<TodoNotifier, List<Todo>>((ref) => TodoNotifier());
页面使用:
class TodoListView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final todos = ref.watch(todoListProvider);return ListView(children: todos.map((t) => ListTile(title: Text(t.title),trailing: IconButton(icon: Icon(Icons.delete),onPressed: () => ref.read(todoListProvider.notifier).remove(t.id),),)).toList(),);}
}
💡 面向对象式的推荐写法,利于维护与测试。
✅ ChangeNotifierProvider
:传统类兼容封装
class AuthModel extends ChangeNotifier {String _email = '';String get email => _email;void login(String email) {_email = email;notifyListeners();}
}final authProvider = ChangeNotifierProvider((ref) => AuthModel());
使用:
class AuthView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final auth = ref.watch(authProvider);return Column(children: [Text('Email: ${auth.email}'),ElevatedButton(onPressed: () => ref.read(authProvider).login('user@example.com'),child: Text('Login'),),],);}
}
⚠️ 尽量用于兼容旧代码或外部库。
✅ FutureProvider
:异步加载数据
final userInfoProvider = FutureProvider<String>((ref) async {await Future.delayed(Duration(seconds: 1));return "Async User Loaded";
});
使用:
class UserInfoWidget extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final userInfo = ref.watch(userInfoProvider);return userInfo.when(data: (name) => Text('User: $name'),loading: () => CircularProgressIndicator(),error: (e, _) => Text('Error: $e'),);}
}
💡 支持 loading/error/data 三种状态,十分方便。
✅ StreamProvider
:实时流监听
final tickProvider = StreamProvider<int>((ref) async* {int count = 0;while (true) {await Future.delayed(Duration(seconds: 1));yield ++count;}
});
使用:
class TimerWidget extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final tick = ref.watch(tickProvider);return tick.when(data: (val) => Text('Tick: $val'),loading: () => Text('Waiting...'),error: (e, _) => Text('Error: $e'),);}
}
💡 非常适合实现 WebSocket、倒计时、后台上传监听等。
🧬 4 Riverpod Provider 的生命周期详解
Riverpod 的每个 Provider
都有清晰的生命周期管理机制,这是它相比 Provider
(老版)或 setState
更加安全、强大的关键优势之一。
生命周期由 Riverpod 自动管理,确保资源释放、缓存优化、避免内存泄漏。
🎯 生命周期触发时机概览
生命周期阶段 | 描述 | 对应钩子函数 / 方法 |
---|---|---|
创建 | 第一次被 ref.watch() / ref.read() 使用 | provider 的构造函数 |
监听中 | 有 widget 或 provider 依赖它 | ref.watch() 触发监听 |
取消监听 | 最后一个监听者移除后,开始进入 dispose 倒计时 | keepAlive 决定回收策略 |
销毁 | 无依赖 + 被标记为回收 | onDispose 触发 |
📌 1. Provider 的创建与首次使用
- 只有在首次使用(如
ref.watch()
)时才真正创建。 - Provider 是懒加载的(Lazy Initialized)。
final timestampProvider = Provider<DateTime>((ref) {print('✅ 创建时间: ${DateTime.now()}');return DateTime.now();
});
📌 2. 自动销毁与缓存策略
🔁 默认行为:自动销毁(AutoDispose)
- 若无任何
ref.watch()
使用该 Provider,它会被自动销毁。 - 优化内存和性能,避免长时间驻留。
final myProvider = Provider.autoDispose<int>((ref) {print('🌀 创建');ref.onDispose(() => print('❌ 销毁'));return 42;
});
使用中断后会触发销毁:
// 页面离开,或 ref.invalidate()
📌 3. 保持活跃 ref.keepAlive()
final counterProvider = Provider.autoDispose<int>((ref) {final link = ref.keepAlive(); // 👈 阻止销毁Future.delayed(Duration(seconds: 30), () {print('🚨 30 秒后允许销毁');link.close(); // 👈 恢复可销毁});ref.onDispose(() {print('⛔ 被销毁');});return 123;
});
✅ 用于防止高频初始化,如网络缓存、状态记录。
📌 4. ref.onDispose()
所有 Provider 都可使用:
ref.onDispose(() {print('🧹 清理资源...');
});
常用于:
- 关闭连接(如 WebSocket、Stream、Timer)
- 释放资源(如 Controller、Database)
- 终止订阅
✅ 总结:各 Provider 生命周期对比
Provider 类型 | 是否可自动销毁 | 是否可 keepAlive | 是否有 onDispose |
---|---|---|---|
Provider | ❌ 否(持久) | ✅ 支持 | ✅ 支持 |
Provider.autoDispose | ✅ 是 | ✅ 支持 | ✅ 支持 |
StateProvider | ❌ 否 | ✅ 支持 | ✅ 支持 |
StateNotifierProvider | ❌ 否(除非手动) | ✅ 支持 | ✅ 支持 |
FutureProvider.autoDispose | ✅ 默认 | ✅ 支持 | ✅ 支持 |
StreamProvider.autoDispose | ✅ 默认 | ✅ 支持 | ✅ 支持 |
🛠 应用实战建议
场景 | 建议 Provider 类型 |
---|---|
临时页面数据(如表单页) | .autoDispose 类型 |
全局共享状态(如登录信息) | 普通 Provider / StateNotifierProvider |
长连接、Timer、Stream | ref.onDispose + .keepAlive() |
一次性请求缓存(配置、Token) | 使用 keepAlive() 手动控制回收 |
✅ 5. 多 Provider 合并管理
final appProviders = ProviderContainer(overrides: []);
或使用 ConsumerStatefulWidget
在生命周期中集中监听多个状态。
🧱 6. Riverpod 与传统Provider 的关系
✅ 简明回答:
Riverpod 并不是基于传统 Provider 的封装,它是 完全重写的一个全新状态管理框架,由同一个作者 Remi Rousselet 开发,但底层逻辑、API 设计、运行机制都不同。
🔍 深度解析:Riverpod 与 Provider 的关系
项目 | Provider | Riverpod |
---|---|---|
作者 | Remi Rousselet | Remi Rousselet |
上线时间 | 2018 | 2020 |
设计理念 | 面向 widget tree 的 InheritedWidget | 独立于 widget tree,可纯 Dart 运行 |
架构关系 | Flutter Widget 的封装 | 重新设计的响应式依赖系统(非封装) |
生命周期 | 依赖 Widget 生命周期 | 由容器独立管理,更安全可控 |
热重载支持 | 差 | 完整支持热重载(尤其适合大型项目) |
Test 测试 | 需依赖 Widget 或 MockContext | 完全脱离 UI,可单测 provider |
🧠 核心区别举例
✅ Provider 示例
ChangeNotifierProvider(create: (_) => CounterModel(),child: MyApp(),
);
- 必须包在 widget tree 里,依赖
BuildContext
。 - 很多依赖关系写在 UI 组件中,不利于拆分测试。
✅ Riverpod 示例
final counterProvider = StateProvider((ref) => 0);
- 不依赖 WidgetTree,任何地方都可以
ref.watch
。 - 甚至可以在纯 Dart 类、后台逻辑中使用,适合模块化架构。
📦 为什么作者重写 Riverpod?
作者自己在 Riverpod 官网解释了:
“Provider 的设计绑定在 widget tree 上,不足以应对复杂、灵活的状态管理需求;Riverpod 是为了解决 Provider 的根本限制而设计的。”
来源:https://riverpod.dev
✅ 总结对比(类比说明)
类比对象 | Provider | Riverpod |
---|---|---|
类比 Flutter 状态 | setState() | Bloc / Redux / MobX |
类比 HTML 框架 | jQuery | React + Hooks |
是否独立可测 | ❌ 需要 widget tree | ✅ 完全支持纯 Dart 单测 |
是否推荐未来使用 | 🟡 小项目可继续用 | ✅ 官方推荐未来项目默认使用 Riverpod |
7. 🔄 Provider 到 Riverpod 迁移指南
✅ 1. 概念映射表
Provider 中的概念 | Riverpod 对应概念 | 用途 |
---|---|---|
ChangeNotifierProvider | ChangeNotifierProvider (兼容) | 保持一致,用于 SDK 封装 |
Provider<T> | Provider<T> | 只读依赖 |
StateProvider<T> (无) | ✅ Riverpod 独有,推荐替代 setState | 管理基本类型如 int、bool |
ConsumerWidget | ConsumerWidget | 响应式 UI |
context.read() | ref.read() | 读取值,不触发 rebuild |
context.watch() | ref.watch() | 读取并监听 |
MultiProvider | ❌ 不需要,Riverpod 使用全局注册 Provider | 提升模块化与性能 |
依赖于 BuildContext | ✅ 不依赖 BuildContext | 更适合逻辑复用、单元测试 |
⚠️ 2. Provider 示例 VS Riverpod 对比代码
旧:使用 Provider(ChangeNotifier)
class CounterModel extends ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}// 注册
ChangeNotifierProvider(create: (_) => CounterModel())// 使用
final counter = Provider.of<CounterModel>(context);
新:使用 Riverpod(StateNotifier)
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {return CounterNotifier();
});class CounterNotifier extends StateNotifier<int> {CounterNotifier() : super(0);void increment() => state++;
}// UI 使用
class CounterWidget extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final count = ref.watch(counterProvider);return Text('$count');}
}
🔁 3. 推荐迁移步骤
步骤 | 内容 |
---|---|
✅ 第一步 | 安装 flutter_riverpod 并用 ProviderScope 包裹 MaterialApp |
✅ 第二步 | 从功能简单的模块开始迁移(如计数器页面) |
✅ 第三步 | 将 ChangeNotifier 转为 StateNotifier / Notifier |
✅ 第四步 | 将 context.read/watch 替换为 ref.read/watch |
✅ 第五步 | 清除旧 Provider 引入,完全替换后删除 Provider |
🤝 4. Riverpod 和 Provider 可以共存吗?
✅ 可以! 它们不会互相干扰,可用于渐进式迁移。
void main() {runApp(MultiProvider(providers: [ChangeNotifierProvider(create: (_) => OldProvider())],child: ProviderScope(child: MyApp(),),),);
}
📌 注意顺序,
ProviderScope
是 Riverpod 的入口容器,MultiProvider
是旧 Provider 的入口。
🧪 5. 测试更简单
Riverpod 的 Provider 不依赖 Widget Tree,可直接测试:
void main() {test('Counter increments', () {final container = ProviderContainer();final notifier = container.read(counterProvider.notifier);notifier.increment();expect(container.read(counterProvider), 1);});
}
🧭 6. 补充推荐迁移写法
✅ 将 Provider 包装类抽离为方法:
Widget build(BuildContext context, WidgetRef ref) {final count = ref.watch(counterProvider);return _buildCountText(count);
}Widget _buildCountText(int count) => Text('$count');
✅ 避免业务逻辑写在 build 方法中,便于测试和维护。
📚 工具推荐
工具 | 用途 |
---|---|
riverpod_lint | Riverpod 专用 Lint |
riverpod_generator | 自动生成 Notifier 等模板 |
state_notifier | 搭配使用,可手动控制状态 |
freezed | 状态模型不可变 + 模式匹配 |
✅ 小结:迁移推荐策略
- 🧱 小项目:直接重构成 Riverpod(更清晰)
- 🧬 中大型项目:新模块优先使用 Riverpod,旧模块稳定后再迁移
- 🧪 单元测试驱动:逻辑类迁移优先(先把模型和 service 拆出来)
- 🔁 可并存:逐步过渡,保持主 app 稳定
下面是一个完整的 计数器 Counter 示例,包括:
- ✅ Provider 旧写法(使用
ChangeNotifier
) - ✅ Riverpod 新写法(使用
StateNotifier
)
每一套代码都包含完整的 main.dart
、model
和 UI
,你可以直接运行进行对比。
✅ 迁移前(使用 Provider)
📄 pubspec.yaml 添加依赖
dependencies:flutter:sdk: flutterprovider: ^6.1.0
📁 counter_model.dart
import 'package:flutter/foundation.dart';class CounterModel extends ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}
📄 main.dart
import '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 { Widget build(BuildContext context) {return MaterialApp(home: CounterPage(),);}
}class CounterPage extends StatelessWidget { Widget build(BuildContext context) {final counter = Provider.of<CounterModel>(context);return Scaffold(appBar: AppBar(title: Text('Provider Counter')),body: Center(child: Text('Count: ${counter.count}', style: TextStyle(fontSize: 24))),floatingActionButton: FloatingActionButton(onPressed: counter.increment,child: Icon(Icons.add),),);}
}
✅ 迁移后(使用 Riverpod)
📄 pubspec.yaml 添加依赖
dependencies:flutter:sdk: flutterflutter_riverpod: ^2.5.1
📁 counter_notifier.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';// Provider 和逻辑
class CounterNotifier extends StateNotifier<int> {CounterNotifier() : super(0);void increment() => state++;void reset() => state = 0;
}final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier(),
);// 🚀 抽离逻辑方法(对外暴露 API)
int useCounter(WidgetRef ref) => ref.watch(counterProvider);void incrementCounter(WidgetRef ref) => ref.read(counterProvider.notifier).increment();void resetCounter(WidgetRef ref) => ref.read(counterProvider.notifier).reset();
📄 main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'counter_controller.dart';void main() {runApp(const ProviderScope(child: MyApp()));
}class MyApp extends StatelessWidget {const MyApp({super.key}); Widget build(BuildContext context) {return MaterialApp(home: CounterPage());}
}class CounterPage extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) {final count = useCounter(ref); // 👈 抽离的读取方法return Scaffold(appBar: AppBar(title: Text('抽离逻辑示例')),body: Center(child: Text('Count: $count', style: TextStyle(fontSize: 24))),floatingActionButton: Row(mainAxisAlignment: MainAxisAlignment.end,children: [FloatingActionButton.small(heroTag: 'add',onPressed: () => incrementCounter(ref), // 👈 抽离的操作方法child: Icon(Icons.add),),const SizedBox(width: 10),FloatingActionButton.small(heroTag: 'reset',onPressed: () => resetCounter(ref), // 👈 抽离 reset 方法child: Icon(Icons.refresh),),],),);}
}
🧭 对比总结
项目 | Provider | Riverpod |
---|---|---|
状态类 | ChangeNotifier | StateNotifier<int> |
状态读取 | Provider.of() | ref.watch() |
状态变更 | notifyListeners() | state = ... |
UI绑定 | StatelessWidget + Provider | ConsumerWidget |
生命周期控制 | 依赖 Widget Tree | 独立容器控制(ProviderScope) |
🧭 8. 最佳实践建议
建议 | 理由或说明 |
---|---|
使用 StateNotifier 替代 ChangeNotifier | 更轻量、更明确、更好测试 |
避免直接 ref.read().state++ | 推荐封装方法防止状态逻辑混乱 |
拆分 Provider 文件 | 提高可读性和可维护性 |
将 ref.read() 写到方法中 | 避免在 UI 中写业务逻辑 |
📦 附加资源推荐
- 官方文档:https://riverpod.dev
- IDE 插件:
Riverpod Snippets
- 推荐组合:Riverpod + go_router + freezed + dio
源码地址
📚 Flutter 状态管理系列文章目录
-
Flutter 状态管理(setState、InheritedWidget、 Provider 、Riverpod、 BLoC / Cubit、 GetX 、MobX 、Redux)
-
setState() 使用详解:原理及注意事项
-
InheritedWidget 组件使用及原理
-
Flutter 中 Provider 的使用、注意事项与原理解析(含代码实战)
-
GetX 用法详细解析以及注意事项
-
Flutter BLoC 使用详细解析
-
Flutter MobX 响应式原理与实战详解
-
Flutter Riverpod 使用详细解析
-
Riverpod原理解析(实现一个自己的Riverpod
相关文章:
Flutter Riverpod 使用详细解析
📚 Flutter 状态管理系列文章目录 Flutter 状态管理(setState、InheritedWidget、 Provider 、Riverpod、 BLoC / Cubit、 GetX 、MobX 、Redux) setState() 使用详解:原理及注意事项 InheritedWidget 组件使用及原理 Flutter 中 Provider 的使用、注…...
算法打卡 day4
4 . 高精度算法 性质:数组或者容器从低位往高位依次存储大整数,方便进位。 4.1 高精度加法 给定两个正整数(不含前导 0),计算它们的和。 输入格式 共两行,每行包含一个整数。 输出格式 共一行,…...
权威认证!华宇TAS应用中间件荣获CCRC“中间件产品安全认证”
近日,华宇TAS应用中间件顺利通过了中国网络安全审查认证和市场监管大数据中心(CCRC)的信息安全认证,获得了IT产品信息安全认证证书。此次获证,标志着华宇TAS应用中间件在安全性、可靠性及合规性等方面达到行业领先水平,可以为政企…...
【Linux网络编程】多路转接IO(二)epoll
目录 epoll初识 epoll的相关系统调用 epoll的工作原理 epoll的优点 epoll的工作方式 水平触发 Level Triggered 工作模式 边缘触发 Edge Triggered 工作模式 对比LT和ET 理解 ET 模式和非阻塞文件描述符 epoll的惊群问题 基于LT模式的epoll代码样例 epoll初识 按照man…...
flutter的包管理#资源管理#调试Flutter应用#Flutter异常捕获
2.5 包管理 2.5.1 简介 在软件开发中,很多时候有一些公共的库或 SDK 可能会被很多项目用到,因此,将这些代码单独抽到一个独立模块,然后哪个项目需要使用时再直接集成这个模块,便可大大提高开发效率。很多编程语言或开…...
Unity Netcode自定义数据传输——结构体及其序列化
在 Unity Netcode 中,要实现自定义数据的网络传输,确实需要两个关键部分: ✅ 两个必需组件: 数据结构定义 public struct PlayerState : INetworkSerializable {public int id; // 字段1:玩家IDpublic bool …...
Vue 3 高级编程技巧
Vue 3 高级编程技巧 1. 计算属性 (Computed Properties) 含义:计算属性在依赖变化时会自动更新。以下是一个示例,展示当 firstName 或 lastName 变化时,fullName 也会更新。 实例: <script setup> import { ref, comput…...
GraphQL注入 -- GPN CTF 2025 Real Christmas
part 1 服务器会每段时间禁用已注册的账号,此处存在漏洞 def deactivate_user_graphql(email):graphql_endpoint current_app.config["GRAPHQL_ENDPOINT"]query f"""mutation {{deactivateUser (user: {{email: "{email}"}}){{ success…...
python打卡day43
疏锦行 作业: kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化 进阶:并拆分成多个文件 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms# 数据预处理 tra…...
ethers.js express vue2 定时任务每天凌晨2点监听合约地址数据同步到Mysql整理
下面是一个完整的 Ethers.js Express Vue2 MySQL 实现方案,用于: 💡每天凌晨 2 点监听某合约地址的 Transfer 事件,写入 MySQL 数据库,并展示每日 NFT 交易量图表(Vue2 ECharts) ✅ 后端部分…...
内网穿透和端口映射的区别在哪?局域网提供互联网访问方案对比选择详解
内网穿透和端口映射是两个经常被提及的概念,它们对于实现网络中的内外网通信起着关键作用。内网穿透和端口映射都能够有效地将本地局域网地址提供给互联网上外网访问,但二者之间存在着显著的区别。 内网穿透与端口映射的核心区别在于实现方式和依赖条件…...
机器学习---正则化、过拟合抑制与特征筛选
专栏:机器学习 个人主页:云端筑梦狮 注:上一篇机器学习还差一小节,日后坑必会填上 一.正则化 什么是正则化 / 如何进行正则化 其实机器学习中正则化(regularization)的外在形式非常简单,就是在模型的损失函数中加…...
优化 ArcPy 脚本性能
合理设置环境变量 优化环境变量配置 ArcPy 提供了许多环境变量,用于控制地理处理工具的行为。合理设置环境变量可以优化脚本的性能。例如,设置“workspace”环境变量可以指定默认的工作空间,避免在脚本中重复指定工作空间路径。 Python 复制…...
Robyn高性能Web框架系列06:使用WebSocket实现产品智能助理
使用WebSocket实现产品智能助理 WebSocket原理与应用场景Robyn的WebSocket基本使用1、创建WebSocket服务2、侦听WebSocket事件3、向客户端发送消息4、向客户端广播消息5、使用查询参数6、主动关闭连接 示例:简易的产品智能助理1、产品数据部分2、产品信息部分3、智能…...
UDP 缓冲区
UDP 有接收缓冲区,没有发送缓冲区 引申问题 1、为什么没有发送缓冲区? 直接引用原文 “因为 UDP 是不可靠的,它不必保存应用进程的数据拷贝,因此无需一个真正的发送缓冲区” 2、没有发送缓冲区的情况下,sendto 的数…...
物联网与低代码:Node-RED如何赋能工业智能化与纵横智控的创新实践
在数字化浪潮席卷全球的今天,物联网(IoT)已从概念走向现实,成为连接物理世界与数字世界的关键桥梁。它通过将日常物品、工业设备等“物”嵌入传感器、软件及其他技术,使其能够通过网络相互连接并交换数据,从…...
【甲方安全视角】开源的安全悖论
文章目录 安全的充分必要条件:从「符号化信任」到「验证驱动安全」构建与分发的不可信链条迭代与审计的节奏错位代码透明与攻击面的对等暴露对普通用户的建议选择可信项目与品牌始终通过官方渠道获取软件注意权限与环境安全对“签名请求”、“连接钱包”等敏感操作保…...
GEO生成式引擎优化发展迅猛:热点数智化传播是GEO最佳路径
在人工智能技术浪潮的推动下,GEO生成式引擎优化已跃升为行业技术演进与产业发展相融合的核心赛道。通过系统性梳理其发展脉络,我们可清晰勾勒出技术突破与产业变革交织的演进轨迹,其发展进程包含以下重要节点。 2023年4月,GPT-4发…...
【unity游戏开发——网络】计算机网络中的三种数据管理模型(分散式、集中式、分布式)和三大通信模型(C/S、B/S、P2P)
注意:考虑到热更新的内容比较多,我将热更新的内容分开,并全部整合放在【unity游戏开发——网络】专栏里,感兴趣的小伙伴可以前往逐一查看学习。 文章目录 一、数据管理模型1、分散式 (Decentralized - 各管各的)2、集中式 (Centra…...
MR30分布式 IO在物流堆垛机的应用
在现代物流行业蓬勃发展的浪潮中,物流堆垛机作为自动化仓储系统的核心设备,承担着货物的高效存取与搬运任务。它凭借自动化操作、高精度定位等优势,极大地提升了仓储空间利用率和货物周转效率。然而,随着物流行业的高速发展&#…...
香港维尔利健康科技集团推出AI辅助医学影像训练平台,助力医护人才数字化转型
香港维尔利健康科技集团近日正式发布其自主研发的“AI辅助医学影像训练平台(V-MedTrain)”,这一创新平台的上线,标志着医学影像教育迈入智能化辅助教学新时代。依托人工智能与大数据分析技术,香港维尔利健康科技集团在…...
2025学年湖北省职业院校技能大赛 “信息安全管理与评估”赛项 样题卷(五)
2025学年湖北省职业院校技能大赛 “信息安全管理与评估”赛项 样题卷(五) 第二部分:网络安全事件响应、数字取证调查、应用程序安全任务书任务 1:应急响应(可以培训有答案)任务 2:通信数据分析取…...
基于 Python 的批量文件重命名软件设计与实现
在工作过程中,经常有很多文件,想要对文件名进行批量改名,特此写了一个程序,以实现此功能。 一、批量文件重命名软件设计原理 (一)核心原理阐述 批量文件重命名软件的核心原理在于运用操作系统提供的文件管理功能,借助编程手段达成对文件名称的批量修改。在这个软件里,…...
【深度学习新浪潮】什么是上下文工程?
什么是上下文工程? 上下文工程(Context Engineering) 是指通过设计、优化与大语言模型(LLM)交互时的输入内容(即“上下文”),引导模型生成更符合预期、更精准回答的系统性方法。这里的“上下文”通常包括 提示词(Prompt)、示例(Few-Shot Examples)、历史对话记录、…...
逆向入门(8)汇编篇-rol指令的学习
还是那个题,这回又碰到个循环左移,有挺多操作方法之前都没有系统的学,用到的时候再看看感觉还挺好,不耽误事 0x00 基本介绍 ROL(Rotate Left): 循环左移,它有两个操作数: 第一个操作数是目标操作数&#…...
Fisco Bcos学习 - 开发第一个区块链应用
文章目录 一、前言二、业务场景分析:简易资产管理系统三、智能合约设计与实现3.1 存储结构设计3.2 接口设计3.3 完整合约代码 四、合约编译与Java接口生成五、SDK配置与项目搭建5.1 获取Java工程项目5.2 项目目录结构5.3 引入Web3SDK5.4 证书与配置文件 六、业务开发…...
黑马python(十六)
目录: 1.JSON数据格式的转换 2.pyecharts模块简介 3.pyecharts入门使用 4.数据准备 5.生成折线图 1.JSON数据格式的转换 2.pyecharts模块简介 官方网站: 画廊网站:有更多的图标形式 测试是否安装 3.pyecharts入门使用 运行会生成一个html的文件&a…...
完成国产化替代!昆明卷烟厂用时序数据库 TDengine 重塑工业时序数据平台
小T导读:昆明卷烟厂作为红云红河烟草(集团)有限责任公司的重要组成部分,是集团卷烟生产的核心工厂。早期在建设制造执行系统(MES)时,其采用了 Wonderware 平台的时序数据存储功能模块࿰…...
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | BackgroundSlider(背景滑块)
📅 我们继续 50 个小项目挑战!—— BackgroundSlider组件 仓库地址:https://github.com/SunACong/50-vue-projects 项目预览地址:https://50-vue-projects.vercel.app/ 使用 Vue 3 的 Composition API 和 <script setup> …...
Wpf的Binding
前言 wpf的Binding就像一个桥梁,它的作用就是连接逻辑层与界面层,既能够把逻辑层的数据搬到界面层展示,又能将界面层的数据更改后传递到逻辑层,Binding的数据来源就是Binding的源,数据展示的地方就是Binding的目标。 …...
Redis—持久化
持久化 在mysql当中,有4个比较关心的特性,分别是原子性、一致性、隔离性和持久性。这里的持久性和持久化是一回事。我们该如何判断是否具有持久性呢?答案就是看重启进程或者主机之后,数据是否存在。当我们把数据存储在硬盘上是就…...
Spring Boot中日志管理与异常处理
以下是Spring Boot中日志管理与异常处理的系统化实践指南,结合最佳实践与核心配置,确保应用健壮性与可维护性。 📊 一、日志管理核心配置 默认框架与级别控制 Logback 是Spring Boot默认日志框架,通过application.yml快速配置&…...
基于MATLAB的BP神经网络的心电图分类方法应用
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 心电图(ECG)是临床诊断心血管疾病的重要工具,能够反映心脏电活动的周期性变化。…...
【笔记】Docker 配置阿里云镜像加速(公共地址即开即用,无需手动创建实例)
2025年06月25日记 【好用但慎用】Windows 系统中将所有 WSL 发行版从 C 盘迁移到 非系统 盘的完整笔记(附 异常处理)-CSDN博客 【笔记】解决 WSL 迁移后 Docker 出现 “starting services: initializing Docker API Proxy: setting up docker ap” 问题…...
Java 中LinkedList 总结
406.根据身高重建队列 力扣题目链接(opens new window) 假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高…...
微信小程序 / UNIAPP --- 阻止小程序返回(顶部导航栏返回、左 / 右滑手势、安卓物理返回键和调用 navigateBack 接口)
目录 理解page-container的原理 设置禁止点击遮盖层关闭? 阻止左滑返回 理解page-container的原理 page-container组件的所有属性,最重要的是show值。在页面上引入这个组件后,若show值为true,页面上所有各种方式触发的返回操作…...
Linux基本指令篇 —— mv指令
在Windows中我们经常使用CtrlX和CtrlV将一个地方的文件或目录移动到另一个地方,我们若是要在Linux当中完成此操作,则需要使用mv指令。mv 是 Linux 系统中用于移动或重命名文件和目录的基本命令之一,是 "move" 的缩写。下面将详细介…...
基于STM32的智能节能风扇的设计
基于STM32的智能节能风扇的设计 内容:1.摘要 本设计旨在解决传统风扇能耗高、功能单一的问题,提出一种基于STM32的智能节能风扇。通过结合温度传感器、人体红外传感器等多种传感器,利用STM32微控制器实现对风扇的智能控制。经过实际测试,该智…...
HCIA-IP路由基础
前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 本篇笔记是根据B站上的视频教程整理而成,感谢UP主的精彩讲解!如果需要了解更多细节,可以参考以下视频…...
Linux 内存管理之page cache
文章目录 一、page cache1.1 File-backed pages和Anonymous pages1.2 page cache/slab cache1.3 读/写路径1.4 脏页回写1.5 drop_caches1.6 时间局部性与空间局部性1.7 Page Cache 的两种类型1.8 关键数据结构 二、Page Cache 的产生2.1 Buffered I/O(标准 I/O&…...
uniApp实战四:网络请求封装
文章目录 1.最终效果预览2.请求封装3.创建config配置文件4.创建api请求5.页面调用 说明:当前笔记基于Vue3开发,HbuilderX版本4.66 1.最终效果预览 2.请求封装 在util/request.js下创建js文件,代码如下 import config from /configconst tim…...
sentinel 自定义 dashboard 用户名密码
默认情况下,sentinel dashboard 用户名密码为 sentinel / sentinel ,这里我使用重写 镜像的方式: // 定义 Dockerfile $ cat Dockerfile # 基于现有 Sentinel Dashboard 镜像 FROM bladex/sentinel-dashboard:1.8.4# 重新定义 ENTRYPOINT&…...
Fisco Bcos学习 - 搭建星形拓扑组网
文章目录 一、前言二、环境准备与依赖安装2.1 系统要求2.2 依赖安装 三、星形拓扑设计与节点规划四、使用build_chain.sh构建星形拓扑4.1 创建操作目录并获取脚本4.2 生成星形拓扑配置文件4.3 执行构建命令4.4 查看生成的节点文件 五、启动节点与共识验证5.1 启动所有节点5.2 查…...
深度学习入门--(二)感知机
一.感知机是什么 简单的输入和输出,感觉(输入),知道(输出,作出反应) 二.简单逻辑电路 2.1与门 import numpy as np #AND def AND(X1,X2):w1,w2,thera0.5,0.5,0.7tmpX1*w1X2*w2if tmp>the…...
LeetCode 3298.统计重新排列后包含另一个字符串的子字符串数目2
给你两个字符串 word1 和 word2 。 如果一个字符串 x 重新排列后,word2 是重排字符串的 前缀 ,那么我们称字符串 x 是 合法的 。 请你返回 word1 中 合法 子字符串 的数目。 注意 ,这个问题中的内存限制比其他题目要 小 ,所以你…...
【nRF52832】【环境搭建 1】【ubuntu下搭建nRF52832开发环境】
本文讲述如何在 ubuntu 22.04 下开发 nRF52832. host 环境说明: $ uname -a Linux leo 6.8.0-60-generic #63~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 22 19:00:15 UTC 2 x86_64 x86_64 x86_64 GNU/Linux1. 安装软件 sudo apt install gcc-arm-none-eabisudo apt-get i…...
Django
1. Django 和 Tornado 的关系 Django 是一个高级 Python Web 框架,它鼓励快速开发和干净、实用的设计。Django 遵循 MVC(模型-视图-控制器)设计模式的一个变种,称为 MTV(模型-模板-视图)。Django 框架提供…...
51c嵌入式~CAN~合集2
我自己的原文哦~ https://blog.51cto.com/whaosoft/14016935 一、CAN总线常见信号干扰问题 定位干扰原因 当总线有干扰时,有经验的工程师能够迅速定位,但是对于新手来说却很麻烦。 造成总线干扰的原因有很多,比如通过电磁辐射耦合到通…...
【iOS】iOS崩溃总结
【iOS】iOS崩溃总结 一、前言 之前写了一篇博文《【Flutter】程序报错导致的灰屏总结》,浏览量、收藏率和点赞量还挺高,还被收录了,就想着总结一下iOS崩溃,这个也是在iOS面试中经常被问到的。 在 iOS 开发过程中,导致…...
npm 报错:“无法加载文件 ...npm.ps1,因为在此系统上禁止运行脚本” 解决方案(附执行策略说明)
在使用 npm 命令时,部分 Windows 用户可能会遇到如下错误: npm : 无法加载文件 D:\nvm4w\nodejs\npm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https://go.microsoft.com/fwlink/?LinkID135170 中的 about_Executi…...