当前位置: 首页 > news >正文

Flutter 学习之旅 之 flutter 使用 SQLite(sqflite) 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装

Flutter 学习之旅 之 flutter 使用 SQLite(sqflite) 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装

目录

Flutter 学习之旅 之 flutter 使用 SQLite(sqflite) 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装

一、简单介绍

1. SharedPreferences

2. Path_provider

3. SQLite

二、sqflite

三、安装 sqflite

四、简单案例实现

五、关键代码


一、简单介绍

Flutter 是一款开源的 UI 软件开发工具包,由 Google 开发和维护。它允许开发者使用一套代码同时构建跨平台的应用程序,包括移动设备(iOS 和 Android)、Web 和桌面平台(Windows、macOS 和 Linux)。

Flutter 使用 Dart 编程语言,它可以将代码编译为 ARM 或 Intel 机器代码以及 JavaScript,从而实现快速的性能。Flutter 提供了一个丰富的预置小部件库,开发者可以根据自己的需求灵活地控制每个像素,从而创建自定义的、适应性强的设计,这些设计在任何屏幕上都能呈现出色的外观和感觉。

在Flutter中,进行本地化保存的方法主要有以下几种:

1. SharedPreferences

SharedPreferences 是一种轻量级的存储方案,适用于存储简单的键值对数据,如字符串、整数、布尔值等

。它类似于Android中的SharedPreferences或iOS中的UserDefaults,使用起来非常方便。

  • 优点:简单易用,适合存储少量数据。

  • 缺点:只能存储基本数据类型,不适合存储大量数据

2. Path_provider

path_provider 插件提供了一种平台无关的方式,用于访问设备的文件系统

。它支持访问两种文件位置系统:

  • 临时文件夹:系统可以随时清空的临时(缓存)文件夹。

  • Documents目录:供应用使用,只有在删除应用时,系统才会清除这个目录

通过path_provider,你可以将数据以文件的形式保存到本地,适合存储一些持久化数据或从网络下载的数据

3. SQLite

SQLite 是一种轻量级的关系型数据库,适用于存储结构化的数据

。它提供了强大的数据查询和管理功能,适合存储大量数据。

  • 优点:功能强大,支持复杂的数据结构和查询。

  • 缺点:使用相对复杂,需要编写SQL语句

二、sqflite

sqflite 是一个用于 Flutter 的 SQLite 数据库插件,允许开发者在移动应用中存储和管理本地数据。它提供了简单易用的 API,支持创建数据库、执行 SQL 查询、插入、更新、删除等操作。sqflite 基于 SQLite,适合存储结构化数据,如用户信息、设置等。它支持 Android 和 iOS 平台,通过 Dart 语言操作,方便与 Flutter 应用集成。使用 sqflite 可以实现数据的持久化存储,提升应用的性能和用户体验。

在开发和使用 sqflite 时,需要注意以下几点以确保代码的正确性和性能优化:

1. 初始化数据库

  • 确保初始化:在使用 sqflite 之前,必须先初始化数据库。通常在应用启动时调用 WidgetsFlutterBinding.ensureInitialized(),然后初始化数据库实例。

  • 数据库路径:使用 getDatabasesPath() 获取数据库存储路径,确保路径正确。

2. 数据库版本管理

  • 版本控制:通过 version 参数管理数据库版本。如果需要更新数据库结构,可以在 onUpgrade 回调中编写升级逻辑。

  • 兼容性:确保升级逻辑兼容旧版本数据,避免数据丢失。

3. 表结构设计

  • 主键设计:合理设计表的主键,避免重复和冲突。例如,使用 INTEGER PRIMARY KEY AUTOINCREMENTTEXT PRIMARY KEY

  • 字段类型:选择合适的字段类型,如 TEXTINTEGERREALBLOB,以优化存储和查询性能。

4. 事务管理

  • 使用事务:对于多个操作(如批量插入或更新),使用事务可以提高性能并确保数据一致性。

    await db.transaction((txn) async {await txn.insert('table', data1);await txn.insert('table', data2);
    });

5. 查询优化

  • 索引:为经常查询的字段创建索引,提高查询效率。

    await db.execute('CREATE INDEX idx_column ON table (column)');
  • 避免全表扫描:尽量使用 WHERE 子句进行条件查询,避免全表扫描。

6. 错误处理

  • 捕获异常:在数据库操作中捕获异常,避免应用崩溃。

    try {await db.insert('table', data);
    } catch (e) {print('Error: $e');
    }

7. 资源管理

  • 关闭数据库:在应用退出或不再需要时关闭数据库连接,释放资源。

    await db.close();

8. 异步操作

  • 使用 await:所有数据库操作都是异步的,使用 await 确保操作完成后再继续执行。

  • 避免阻塞主线程:确保数据库操作不会阻塞主线程,影响用户体验。

9. 测试

  • 单元测试:编写单元测试验证数据库操作的正确性。

  • 模拟数据:在测试环境中使用模拟数据,避免依赖真实数据。

10. 安全性

  • SQL 注入:使用参数化查询,避免 SQL 注入攻击。

    await db.query('table', where: 'column = ?', whereArgs: [value]);

11. 备份和恢复

  • 备份数据:定期备份数据库文件,防止数据丢失。

  • 恢复数据:提供恢复机制,允许用户从备份中恢复数据。

12. 日志和调试

  • 启用日志:在开发过程中启用日志,方便调试。

    await db.execute('PRAGMA journal_mode=WAL');

通过遵循这些注意事项,可以确保 sqflite 的使用更加高效、稳定和安全,提升应用的整体质量。

三、安装 sqflite

1、直接运行命令:flutter pub add sqflite

2、或者在 pubspec.yaml 添加

dependencies:sqflite: ^2.4.2

四、简单案例实现

1、这里使用 Android Studio 进行创建 Flutter 项目

2、创建一个 application 的 Flutter 项目

3、项目结构如下


 

4、编写一个 DatabaseHelper

5、在 main 中编写一个测试代码

6、运行打印如下

7、继续编写一个复杂些的

8、在 main 中编写一个测试代码

9、运行打印如下

五、关键代码

1、DatabaseHelper 一

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';class DatabaseHelper {// 数据库文件名static const String dbName = "localization.db";// 数据库版本号,用于版本控制和升级static const int dbVersion = 1;// 数据表名,用于存储本地化数据static const String tableLocalization = "localization";// 数据表中的键字段名static const String columnKey = "key";// 数据表中的值字段名static const String columnValue = "value";// 私有数据库实例变量,用于存储数据库连接Database? _database;// 获取数据库实例的公共方法// 如果数据库已经初始化,则直接返回;否则初始化数据库并返回Future<Database> get database async {if (_database != null) return _database!;_database = await _initDatabase();return _database!;}// 初始化数据库的方法Future<Database> _initDatabase() async {// 获取设备的数据库存储路径String path = join(await getDatabasesPath(), dbName);// 打开或创建数据库文件// 如果数据库不存在,则会调用 onCreate 回调方法来创建表return await openDatabase(path, version: dbVersion, onCreate: _onCreate);}// 数据库创建时调用的回调方法// 用于创建数据表结构Future<void> _onCreate(Database db, int version) async {// 执行 SQL 语句,创建 localization 表// 表包含两个字段:key(主键,唯一)和 valueawait db.execute('''CREATE TABLE $tableLocalization ($columnKey TEXT PRIMARY KEY, // 键字段,作为主键$columnValue TEXT // 值字段)''');}// 保存本地化数据的方法Future<void> saveLocalization(String key, String value) async {// 获取数据库实例Database db = await database;// 插入数据到 localization 表// 如果 key 已存在,则使用 ConflictAlgorithm.replace 策略替换原有数据await db.insert(tableLocalization, {columnKey: key, columnValue: value},conflictAlgorithm: ConflictAlgorithm.replace);}// 获取本地化数据的方法Future<String?> getLocalization(String key) async {// 获取数据库实例Database db = await database;// 查询 localization 表,查找指定 key 的数据List<Map<String, dynamic>> result = await db.query(tableLocalization,where: '$columnKey = ?', whereArgs: [key]);// 如果查询结果不为空,返回 value 字段的值;否则返回 nullreturn result.isNotEmpty ? result.first[columnValue] as String? : null;}// 移除本地化数据的方法Future<void> removeLocalization(String key) async {// 获取数据库实例Database db = await database;// 从 localization 表中删除指定 key 的数据await db.delete(tableLocalization, where: '$columnKey = ?', whereArgs: [key]);}// 判断是否存在指定 key 的本地化数据的方法Future<bool> hasLocalization(String key) async {// 获取数据库实例Database db = await database;// 查询 localization 表,查找指定 key 的数据List<Map<String, dynamic>> result = await db.query(tableLocalization,where: '$columnKey = ?', whereArgs: [key]);// 如果查询结果不为空,返回 true;否则返回 falsereturn result.isNotEmpty;}
}

代码说明

  1. 常量定义

    • dbName:定义数据库文件的名称。

    • dbVersion:定义数据库的版本号,用于版本控制和升级。

    • tableLocalization:定义存储本地化数据的表名。

    • columnKeycolumnValue:定义表中的字段名,分别用于存储键和值。

  2. 数据库初始化

    • _initDatabase 方法通过 getDatabasesPath 获取设备的数据库存储路径,并使用 openDatabase 打开或创建数据库文件。

    • 如果数据库文件不存在,则会调用 _onCreate 方法来创建表结构。

  3. 表结构创建

    • _onCreate 方法中,使用 SQL 语句创建 localization 表,包含两个字段:key(主键,唯一)和 value

  4. 数据操作方法

    • saveLocalization:插入或更新数据到 localization 表。

    • getLocalization:查询指定 key 的数据,返回对应的 value

    • removeLocalization:删除指定 key 的数据。

    • hasLocalization:判断是否存在指定 key 的数据。

通过这些注释,你可以更清晰地理解每个方法的作用和实现逻辑,便于在项目中使用和维护。

2、main 一

import 'package:flutter/material.dart'; // 导入 Flutter 的 Material 组件库
import 'package:test_sqflite_0317/database_helper.dart'; // 导入封装的 DatabaseHelper 类void main() async {// 确保 Flutter 绑定初始化// 在使用 Flutter 的异步操作(如数据库操作)之前,需要调用此方法来初始化 Flutter 的绑定。// 这是 Flutter 应用程序启动时的必要步骤,确保可以使用 Flutter 提供的异步功能。WidgetsFlutterBinding.ensureInitialized();// 创建 DatabaseHelper 的实例// DatabaseHelper 是一个封装类,用于管理本地化数据的保存、获取、移除等操作。var dbHelper = DatabaseHelper();// 保存数据到数据库// 调用 DatabaseHelper 的 saveLocalization 方法,将键 'language' 和值 'en' 保存到数据库中。// 这里的 'language' 是一个示例键,'en' 是对应的值,表示语言设置为英语。await dbHelper.saveLocalization('language', 'en');// 从数据库中获取保存的数据// 调用 DatabaseHelper 的 getLocalization 方法,通过键 'language' 获取对应的值。// 如果数据库中存在该键,则返回对应的值;否则返回 null。String? language = await dbHelper.getLocalization('language');// 打印获取到的语言设置// 如果成功获取到值,则打印 'Saved language: en';否则打印 'Saved language: null'。print('Saved language: $language');// 判断数据库中是否有保存的数据// 调用 DatabaseHelper 的 hasLocalization 方法,检查键 'language' 是否存在于数据库中。// 如果存在,返回 true;否则返回 false。bool hasLanguage = await dbHelper.hasLocalization('language');// 打印判断结果// 如果存在该键,则打印 'Has language: true';否则打印 'Has language: false'。print('Has language: $hasLanguage');// 从数据库中移除保存的数据// 调用 DatabaseHelper 的 removeLocalization 方法,通过键 'language' 删除对应的记录。await dbHelper.removeLocalization('language');// 再次判断数据库中是否有保存的数据// 再次调用 hasLocalization 方法,检查键 'language' 是否还存在于数据库中。hasLanguage = await dbHelper.hasLocalization('language');// 打印判断结果// 由于已经删除了该键,因此打印 'Has language after removal: false'。print('Has language after removal: $hasLanguage');
}

代码说明

  1. 导入必要的库

    • flutter/material.dart:导入 Flutter 的 Material 组件库,用于构建 Flutter 应用。

    • test_sqflite_0317/database_helper.dart:导入封装的 DatabaseHelper 类,该类提供了数据库操作的接口。

  2. 初始化 Flutter 绑定

    • WidgetsFlutterBinding.ensureInitialized():在使用 Flutter 的异步操作之前,必须调用此方法来初始化 Flutter 的绑定。这是 Flutter 应用程序启动时的必要步骤。

  3. 创建 DatabaseHelper 实例

    • var dbHelper = DatabaseHelper():创建 DatabaseHelper 的实例,用于后续的数据库操作。

  4. 保存数据

    • await dbHelper.saveLocalization('language', 'en'):调用 DatabaseHelpersaveLocalization 方法,将键 'language' 和值 'en' 保存到数据库中。

  5. 获取保存的数据

    • String? language = await dbHelper.getLocalization('language'):调用 DatabaseHelpergetLocalization 方法,通过键 'language' 获取对应的值。

    • print('Saved language: $language'):打印获取到的语言设置。

  6. 判断是否有保存的数据

    • bool hasLanguage = await dbHelper.hasLocalization('language'):调用 DatabaseHelperhasLocalization 方法,检查键 'language' 是否存在于数据库中。

    • print('Has language: $hasLanguage'):打印判断结果。

  7. 移除保存的数据

    • await dbHelper.removeLocalization('language'):调用 DatabaseHelperremoveLocalization 方法,通过键 'language' 删除对应的记录。

  8. 再次判断是否有保存的数据

    • hasLanguage = await dbHelper.hasLocalization('language'):再次调用 hasLocalization 方法,检查键 'language' 是否还存在于数据库中。

    • print('Has language after removal: $hasLanguage'):打印判断结果。

通过这些注释,你可以更清晰地理解代码的逻辑和功能,便于在项目中使用和维护。

3、DatabaseHelper 二

import 'package:sqflite/sqflite.dart'; // 导入 sqflite 包,用于操作 SQLite 数据库
import 'package:path/path.dart'; // 导入 path 包,用于处理文件路径class DatabaseHelper {// 数据库文件名static const String dbName = "user_management.db";// 数据库版本号,用于版本控制和升级static const int dbVersion = 1;// 数据表名,用于存储用户信息static const String tableUsers = "users";// 数据表中的用户ID字段名,主键static const String columnId = "id";// 数据表中的用户姓名字段名static const String columnName = "name";// 数据表中的用户邮箱字段名,唯一约束static const String columnEmail = "email";// 私有数据库实例变量,用于存储数据库连接Database? _database;// 获取数据库实例的公共方法// 如果数据库已经初始化,则直接返回;否则初始化数据库并返回Future<Database> get database async {if (_database != null) return _database!;_database = await _initDatabase();return _database!;}// 初始化数据库的方法// 获取数据库存储路径,并打开或创建数据库文件Future<Database> _initDatabase() async {// 使用 getDatabasesPath 获取设备的数据库存储路径String path = join(await getDatabasesPath(), dbName);// 打开或创建数据库文件,指定版本号和 onCreate 回调方法return await openDatabase(path, version: dbVersion, onCreate: _onCreate);}// 数据库创建时调用的回调方法// 用于创建数据表结构Future<void> _onCreate(Database db, int version) async {// 执行 SQL 语句,创建 users 表// 表包含三个字段:id(自增主键)、name(非空)、email(非空且唯一)await db.execute('''CREATE TABLE $tableUsers ($columnId INTEGER PRIMARY KEY AUTOINCREMENT, // 用户ID,自增主键$columnName TEXT NOT NULL, // 用户姓名,非空$columnEmail TEXT NOT NULL UNIQUE // 用户邮箱,非空且唯一)''');}// 插入用户数据的方法Future<int> insertUser(Map<String, dynamic> user) async {// 获取数据库实例Database db = await database;// 插入数据到 users 表,返回插入的行IDreturn await db.insert(tableUsers, user);}// 查询所有用户的方法Future<List<Map<String, dynamic>>> getAllUsers() async {// 获取数据库实例Database db = await database;// 查询 users 表,返回所有用户数据return await db.query(tableUsers);}// 根据ID查询用户的方法Future<Map<String, dynamic>?> getUserById(int id) async {// 获取数据库实例Database db = await database;// 查询 users 表,查找指定ID的用户List<Map<String, dynamic>> result = await db.query(tableUsers,where: '$columnId = ?', // 查询条件whereArgs: [id], // 查询参数);// 如果查询结果不为空,返回第一个结果;否则返回 nullreturn result.isNotEmpty ? result.first : null;}// 更新用户数据的方法Future<int> updateUser(Map<String, dynamic> user) async {// 获取数据库实例Database db = await database;// 更新 users 表中的指定用户数据,返回更新的行数return await db.update(tableUsers,user,where: '$columnId = ?', // 更新条件whereArgs: [user[columnId]], // 更新参数);}// 删除用户的方法Future<int> deleteUser(int id) async {// 获取数据库实例Database db = await database;// 删除 users 表中的指定用户,返回删除的行数return await db.delete(tableUsers,where: '$columnId = ?', // 删除条件whereArgs: [id], // 删除参数);}// 关闭数据库的方法Future<void> closeDatabase() async {// 如果数据库实例不为空,则关闭数据库连接if (_database != null) {await _database!.close();_database = null;}}
}

代码说明

  1. 常量定义

    • dbName:定义数据库文件的名称。

    • dbVersion:定义数据库的版本号,用于版本控制和升级。

    • tableUsers:定义存储用户信息的表名。

    • columnIdcolumnNamecolumnEmail:定义表中的字段名。

  2. 数据库实例

    • _database:私有变量,用于存储数据库连接实例。

  3. 获取数据库实例

    • database:公共方法,用于获取数据库实例。如果数据库已经初始化,则直接返回;否则调用 _initDatabase 初始化数据库。

  4. 初始化数据库

    • _initDatabase:获取数据库存储路径,并打开或创建数据库文件。如果数据库不存在,则调用 _onCreate 方法创建表结构。

  5. 创建表

    • _onCreate:创建 users 表,包含三个字段:id(自增主键)、name(非空)、email(非空且唯一)。

  6. 数据操作方法

    • insertUser:插入用户数据到 users 表,返回插入的行ID。

    • getAllUsers:查询 users 表,返回所有用户数据。

    • getUserById:根据用户ID查询用户数据,返回查询结果或 null

    • updateUser:更新指定用户的数据,返回更新的行数。

    • deleteUser:删除指定用户,返回删除的行数。

    • closeDatabase:关闭数据库连接,释放资源。

通过这些注释,你可以更清晰地理解代码的逻辑和功能,便于在项目中使用和维护。

4、main 二

import 'package:flutter/material.dart'; // 导入 Flutter 的 Material 组件库
import 'database_helper.dart'; // 导入封装的 DatabaseHelper 类void main() async {// 确保 Flutter 绑定初始化// 在使用 Flutter 的异步操作(如数据库操作)之前,必须调用此方法来初始化 Flutter 的绑定。// 这是 Flutter 应用程序启动时的必要步骤,确保可以使用 Flutter 提供的异步功能。WidgetsFlutterBinding.ensureInitialized();// 创建 DatabaseHelper 的实例// DatabaseHelper 是一个封装类,用于管理用户数据的保存、查询、更新和删除等操作。var dbHelper = DatabaseHelper();// 插入用户数据// 调用 DatabaseHelper 的 insertUser 方法,将用户数据(姓名和邮箱)插入到数据库中。// 这里插入了一个示例用户,姓名为 'John Doe',邮箱为 'john.doe@example.com'。await dbHelper.insertUser({'name': 'John Doe','email': 'john.doe@example.com'});// 查询所有用户// 调用 DatabaseHelper 的 getAllUsers 方法,查询数据库中的所有用户数据。// 返回的是一个包含所有用户信息的列表,每个用户信息是一个 Map。List<Map<String, dynamic>> users = await dbHelper.getAllUsers();// 打印所有用户数据print('All users: $users');// 根据ID查询用户// 调用 DatabaseHelper 的 getUserById 方法,通过用户ID查询特定用户的数据。// 这里查询ID为1的用户。Map<String, dynamic>? user = await dbHelper.getUserById(1);// 打印查询到的用户数据print('User with ID 1: $user');// 更新用户数据// 调用 DatabaseHelper 的 updateUser 方法,更新特定用户的数据。// 这里将ID为1的用户姓名更新为 'Jane Doe',邮箱更新为 'jane.doe@example.com'。await dbHelper.updateUser({'id': 1,'name': 'Jane Doe','email': 'jane.doe@example.com'});// 查询更新后的用户// 再次调用 getUserById 方法,查询更新后的用户数据。user = await dbHelper.getUserById(1);// 打印更新后的用户数据print('Updated user with ID 1: $user');// 删除用户// 调用 DatabaseHelper 的 deleteUser 方法,删除特定用户。// 这里删除ID为1的用户。await dbHelper.deleteUser(1);// 查询所有用户(验证删除操作)// 再次调用 getAllUsers 方法,查询数据库中的所有用户数据,验证删除操作是否成功。users = await dbHelper.getAllUsers();// 打印删除后的所有用户数据print('All users after deletion: $users');// 关闭数据库// 调用 DatabaseHelper 的 closeDatabase 方法,关闭数据库连接,释放资源。await dbHelper.closeDatabase();
}

代码说明

  1. 导入必要的库

    • flutter/material.dart:导入 Flutter 的 Material 组件库,用于构建 Flutter 应用。

    • database_helper.dart:导入封装的 DatabaseHelper 类,该类提供了数据库操作的接口。

  2. 初始化 Flutter 绑定

    • WidgetsFlutterBinding.ensureInitialized():在使用 Flutter 的异步操作之前,必须调用此方法来初始化 Flutter 的绑定。这是 Flutter 应用程序启动时的必要步骤。

  3. 创建 DatabaseHelper 实例

    • var dbHelper = DatabaseHelper():创建 DatabaseHelper 的实例,用于后续的数据库操作。

  4. 插入用户数据

    • await dbHelper.insertUser({...}):调用 DatabaseHelperinsertUser 方法,将用户数据(姓名和邮箱)插入到数据库中。

  5. 查询所有用户

    • List<Map<String, dynamic>> users = await dbHelper.getAllUsers():调用 DatabaseHelpergetAllUsers 方法,查询数据库中的所有用户数据。

    • print('All users: $users'):打印所有用户数据。

  6. 根据ID查询用户

    • Map<String, dynamic>? user = await dbHelper.getUserById(1):调用 DatabaseHelpergetUserById 方法,通过用户ID查询特定用户的数据。

    • print('User with ID 1: $user'):打印查询到的用户数据。

  7. 更新用户数据

    • await dbHelper.updateUser({...}):调用 DatabaseHelperupdateUser 方法,更新特定用户的数据。

  8. 查询更新后的用户

    • user = await dbHelper.getUserById(1):再次调用 getUserById 方法,查询更新后的用户数据。

    • print('Updated user with ID 1: $user'):打印更新后的用户数据。

  9. 删除用户

    • await dbHelper.deleteUser(1):调用 DatabaseHelperdeleteUser 方法,删除特定用户。

  10. 查询所有用户(验证删除操作)

    • users = await dbHelper.getAllUsers():再次调用 getAllUsers 方法,查询数据库中的所有用户数据,验证删除操作是否成功。

    • print('All users after deletion: $users'):打印删除后的所有用户数据。

  11. 关闭数据库

    • await dbHelper.closeDatabase():调用 DatabaseHelpercloseDatabase 方法,关闭数据库连接,释放资源。

通过这些注释,你可以更清晰地理解代码的逻辑和功能,便于在项目中使用和维护。

相关文章:

Flutter 学习之旅 之 flutter 使用 SQLite(sqflite) 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装

Flutter 学习之旅 之 flutter 使用 SQLite&#xff08;sqflite&#xff09; 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装 目录 Flutter 学习之旅 之 flutter 使用 SQLite&#xff08;sqflite&#xff09; 实现简单的数据本地化 保存/获取/移除/判断是否存在…...

[unity 组件] Content Size Fitter 横向填充不满解决办法

可以看到&#xff0c;当只有3个或者4个元素的时候&#xff0c;布局组件并没有将横向宽度占满来布局。之所以有此困惑的原因是我以为他的布局策略是&#xff0c;从左到右&#xff0c;从上至下&#xff0c;尽量占满空间&#xff0c;不够了再换行&#xff0c;其实不然。 5到6个元…...

Dify 项目开源大模型应用开发平台

Dify 是一款开源的大语言模型&#xff08;LLM&#xff09;应用开发平台&#xff0c;旨在简化生成式 AI 应用的创建、部署和持续优化流程。以下从多个维度对该项目进行详细介绍&#xff1a; 一、项目定义与核心功能 Dify 的核心定位是结合 后端即服务&#xff08;BaaS&#xff…...

使用 `pytest` 框架时,可以通过极限封装将 YAML 文件的读取、解析

在使用 pytest 框架时,可以通过极限封装将 YAML 文件的读取、解析和测试用例的通用逻辑封装成共享的方法或 fixture,从而减少重复代码。以下是详细的实现步骤和示例。 1. 封装 YAML 文件读取和解析 将 YAML 文件的读取和解析逻辑封装到一个工具函数中,供所有测试用例调用。…...

算法刷题记录——LeetCode篇(2) [第101~200题](持续更新)

(优先整理热门100及面试150&#xff0c;不定期持续更新&#xff0c;欢迎关注) 101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&am…...

ruoyi 小程序使用笔记

1.上传图片 页面 <uni-forms-item label"退休证明(退休证)" name"retire"><uni-file-picker ref"imageUploadRetire" :limit"1" :auto-upload"false" select"upload"/> </uni-forms-item>js …...

计算机网络——总结

01. 网络的发展及体系结构 网络演进历程 从1969年ARPANET的4个节点发展到如今覆盖全球的互联网&#xff0c;网络技术经历了电路交换到分组交换、有线连接到无线覆盖的革命性变革。5G时代的到来使得网络传输速度突破10Gbps&#xff0c;物联网设备数量突破百亿级别。 网络体系…...

Stable Diffusion lora训练(一)

一、不同维度的LoRA训练步数建议 2D风格训练 数据规模&#xff1a;建议20-50张高质量图片&#xff08;分辨率≥10241024&#xff09;&#xff0c;覆盖多角度、多表情的平面风格。步数范围&#xff1a;总步数控制在1000-2000步&#xff0c;公式为 总步数 Repeat Image Epoch …...

再学:ERC20-Permit2、SafeERC20方法 详解ERC721,如何铸造一个NFT以及IPFS的作用

目录 1.Permit2 2.尽量使用Safe方法 3.ERC721 4. 铸造NFT 1.Permit2 针对没有permit的代币实现的线下签名方式 通过approve方法&#xff0c;让Permit2拿到无限次数的授权。拿到授权之后&#xff0c;Permit2会生成签名。 当用户需要转账的时候&#xff0c;Permit2会发送签…...

Docker 存储

目录挂载 在执行run时设置参数-v即可实现目录映射, 实现原理会在宿主机器创建一个空文件夹 # 挂载宿主机的 /data 目录到容器的 /app 目录 docker run -d -v /data:/app --name my-app my-image # 挂载 docker 内的 /usr/share/nginx/html 目录到本地机的 /app/nghtml docker…...

详细介绍VUE,带你了解VUE!!!

Vue.js 是一个渐进式的 JavaScript 框架&#xff0c;用于构建用户界面。它的核心库专注于视图层&#xff0c;易于与其它库或现有项目进行集成&#xff0c;同时也可以与现代工具链和支持库结合使用&#xff0c;成为一个完整的开发框架。 以下是关于 Vue.js 的详细资料&#xff…...

C++语法之命名空间二

A.h头文件中代码&#xff1a; namespace a {void 输出(); }; A.cpp源文件中代码&#xff1a; #include <iostream> #include "A.h" void a::输出() {std::cout << "A.h里的输出函数" << std::endl; } B.h头文件中代码&#xff1a; …...

【STM32】I²CC通信外设硬件I²CC读写MPU6050(学习笔记)

相关文章笔记&#xff1a; 【STM32】I2C通信协议&MPU6050芯片-学习笔记-CSDN博客 【江协科技STM32】软件I2C协议层读写MPU6050驱动层-CSDN博客 IC通信外设 IC外设简介 STM32内部集成了硬件I2C收发电路&#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答…...

Android Room 框架公共模块源码深度剖析(四)

一、引言 在 Android 开发中&#xff0c;数据持久化是一个常见的需求。Android Room 框架作为 Android Jetpack 组件的一部分&#xff0c;为开发者提供了一个抽象层&#xff0c;使得在 SQLite 数据库上进行数据操作变得更加简单和高效。Room 框架包含多个模块&#xff0c;其中…...

NumPy系列 - 创建矩阵

目录 前传直接创建数组就只是创建数组1. np.array()2. np.arange()3. np.ones()4. numpy.ones_like()5. np.zeros()6. numpy.zeros_like() 定义数据类型 参考资料 前传 由于&#xff0c;某人在上智能相关课程的时候&#xff0c;总想着一大堆的事情&#xff0c;统计股市涨跌&am…...

能“嘎嘎提升”提升用户居住体验的智能家居物联网框架推荐!

智能家居在日常生活中给我们的带来了更多的便利&#xff0c;更让有些用户切实地体会到了科技的魅力&#xff0c;对于想要打造属于自己的智能家居氛围感的用户们&#xff0c;以下是一些能够帮助提升居住体验的智能家居物联网框架及应用&#xff1a; 1. 涂鸦智能&#xff08;Tuy…...

python-leetcode 60.分割回文串

题目&#xff1a; 给定一个字符串S,请将S分割成一些子串&#xff0c;使每个子串都是回文串&#xff0c;返回S所有可能的分割方案 方法一&#xff1a;回溯深度优先搜索 1. 主要思想 使用 深度优先搜索&#xff08;DFS&#xff09; 遍历 s 的所有可能划分方式。使用 回溯&…...

Android Jetpack Compose介绍

Android Jetpack Compose Android Jetpack Compose 是 Google 推出的现代 UI 工具包&#xff0c;用于以声明式的方式构建 Android 应用的 UI。它摒弃了传统的 XML 布局方式&#xff0c;完全基于 Kotlin 编写&#xff0c;提供了更简洁、更强大的 UI 开发体验。以下是 Compose 的…...

文档搜索引擎项目测试

目录 设计测试用例 功能测试 文档搜索功能 具体的逻辑 文档显示搜索结果功能 自动化测试 功能类介绍 最终测试套件的测试结果 性能测试 查看聚合报告 每秒处理事务数/吞吐量(TPS) 响应时间 生成测试报告 界面测试 初始页面 搜索页面 总结 后续改进: 设计测试…...

Vue3项目技术点记录

vue3项目技术点笔记 1 环境变量 - 不同环境用不同的配置 环境变量命名:.env.produciton .env.development Vite.config.ts 配置 envDir:‘’ 链接: VUE3+Vite 环境变量配置 2 axios的封装 http请求拦截,响应拦截。 src下建立公共文件夹Utils下建立request.ts import axios…...

一和零 (leetcode 474

leetcode系列 文章目录 一、核心操作二、外层配合操作三、核心模式代码总结 本题是一个01背包问题&#xff0c;只是背包是一个二维数组的背包&#xff0c;分别为0的个数不能超过m&#xff0c;1的个数不能超过n&#xff0c;而物品就是题目中的字符串&#xff0c;其容量为0和1的…...

Linux vim mode | raw / cooked

注&#xff1a;机翻&#xff0c;未校。 vim terminal “raw” mode Vim 终端 “raw” 模式 1. 原始模式与已处理模式的区别 We know vim puts the terminal in “raw” mode where it receives keystrokes as they are typed, opposed to “cooked” mode where the command…...

利用Linux的I2C子系统和i2c-tools工具集写出的对I2C设备AP3216C读写的应用程序

前言 由于NXP官方提供的BSP里已经包含了其片上I2C控制器的驱动并接入到了Linux的I2C子系统&#xff0c;所以我们可以直接去写与I2C有关的应用程序了。 在本篇博文中我们用两种方式对I2C设备AP3216C进行读写操作。 第一种&#xff1a;直接利用Linux的I2C子系统对I2C设备AP3216…...

springCloud集成tdengine(原生和mapper方式) 其二 原生篇

mapper篇请看另一篇文章 一、引入pom文件 <!-- TDengine 连接器--><dependency><groupId>com.taosdata.jdbc</groupId><artifactId>taos-jdbcdriver</artifactId><version>3.5.3</version></dependency>二、在nacos中填…...

gralloc usage flags

下面这些示例主要说明了 gralloc usage flags 在图像处理和多媒体应用中如何影响性能和正确性。让我们逐个详细分析每个问题的 根因 和 修复方案&#xff0c;并深入解析 gralloc 标志对 缓存管理 和 数据流 的影响。 ✅ Example 1: 长曝光快照耗时异常 &#x1f4cc; 问题描述…...

RIP路由欺骗攻击与防御实验详解

一、基础网络配置 1. 路由器R1配置 interface GigabitEthernet0/0/0ip address 192.1.2.254 255.255.255.0 ! interface GigabitEthernet0/0/1ip address 192.1.3.254 255.255.255.0 ! router rip 1version 2network 192.1.2.0network 192.1.3.0 2. 路由器R2配置 interface…...

在 Linux下使用 Python 3.11 和 FastAPI 搭建带免费证书的 HTTPS 服务器

在当今数字化时代&#xff0c;保障网站数据传输的安全性至关重要。HTTPS 协议通过使用 SSL/TLS 加密技术&#xff0c;能够有效防止数据在传输过程中被窃取或篡改。本教程将详细介绍如何在 Ubuntu 22.04 系统上&#xff0c;使用 Python 3.11 和 FastAPI 框架搭建一个带有免费 SS…...

[QMT量化交易小白入门]-三十五、如何将聚宽策略信号转为QMT实盘交易

本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读一、聚宽模拟运行:构建交易策略的基础在聚宽…...

国思RDIF低代码快速开发框架 v6.2版本发布

1、平台介绍 国思RDIF企业级低代码开发平台&#xff0c;给用户和开发者最佳的框架平台方案&#xff0c;为企业快速构建跨平台、企业级的应用提供强大支持。致力于解决企业信息化项目交付难、实施效率低、开发成本高的问题。能帮助企业快速构建美观易用、架构专业、安全可控的企…...

学习笔记 ASP.NET Core Web API 8.0部署到iis

一.修改配置文件 修改Program.cs配置文件将 if (app.Environment.IsDevelopment()) {app.UseSwagger();app.UseSwaggerUI(); }修改为 app.UseSwagger(); app.UseSwaggerUI(); 二.安装ASP.NET Core Runtime 8.0.14 文件位置https://dotnet.microsoft.com/en-us/download/do…...

【Linux】信号:产生信号

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;linux笔记仓 目录 01.信号信号处理简单理解信号的发送和保存由软件产生的信号由硬件&#xff08;异常&#xff09;产生的信号 01.信号 进程信号是操作系统提供的一种异步通知机制&#xff0c;用于…...

单片机自学总结

自从工作以来&#xff0c;一直努力耕耘单片机&#xff0c;至今&#xff0c;颇有收获。从51单片机&#xff0c;PIC单片机&#xff0c;直到STM32&#xff0c;以及RTOS和Linux&#xff0c;几乎天天在搞:51单片机&#xff0c;STM8S207单片机&#xff0c;PY32F003单片机&#xff0c;…...

Idea集成docker通过ca加密实现镜像打包

​ Idea集成docker实现镜像打包_ideadocker镜像打包-CSDN博客 ​ 之前通过这种方式虽然可以实现idea通过maven打jar包的同时把docker镜像也进行打包&#xff0c;但是这种方式存在很大漏洞&#xff0c;就是服务器的2375端口大开&#xff0c;任何人拿着idea通过这种方式都可以连…...

【Prometheus】prometheus标签替换label_replace,动态修改生成标签,增强查询的灵活性和表达能力

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...

蓝桥杯 之 暴力回溯

文章目录 数字接龙小u的最大连续移动次数问题 在蓝桥杯中&#xff0c;十分喜欢考察对于网格的回溯的问题&#xff0c;对于这类的问题&#xff0c;常常会使用到这个DFS和BFS进行考察&#xff0c;不过无论怎么考察&#xff0c;都只是会在最基础的模本的基础上&#xff0c;根据这个…...

在K8S中挂载 Secret 到 Pod

在 Kubernetes 里&#xff0c;把 Secret 挂载到 Pod 中有两种主要方式&#xff1a;作为卷挂载和作为环境变量挂载。下面为你提供相应的代码示例。 作为卷挂载 Secret 将 Secret 作为卷挂载到 Pod 时&#xff0c;Secret 的每个键会成为挂载目录下的一个文件&#xff0c;文件内…...

LINUX网络编程API原型详细解析

1. 网络体系 1.1. 简介 网络采用分而治之的方法设计&#xff0c;将网络的功能划分为不同的模块&#xff0c;以分层的形式有机组合在一起。 每层实现不同的功能&#xff0c;其内部实现方法对外部其他层次来说是透明的。每层向上层提供服务&#xff0c;同时使用下层提供…...

Android 13 Launcher3最近任务列表“全部清除“按钮位置优化实战

一、问题背景与实现难点 在Android 13横屏设备开发中&#xff0c;系统默认将最近任务列表的"全部清除"按钮布局在屏幕左侧&#xff0c;这与用户习惯的底部布局存在明显差异。相较于Android 8.1时代SystemUI模块的实现&#xff0c;Android 13将相关逻辑迁移至Launche…...

docker最新源,及遇到问题+处理

目前国内可用Docker镜像源汇总&#xff08;截至2025年3月&#xff09; - CoderJia 遇到问题&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:13287->[:…...

Python简单爬虫实践案例

学习目标 能够知道Web开发流程 能够掌握FastAPI实现访问多个指定网页 知道通过requests模块爬取图片 知道通过requests模块爬取GDP数据 能够用pyecharts实现饼图 能够知道logging日志的使用 一、基于FastAPI之Web站点开发 1、基于FastAPI搭建Web服务器 # 导入FastAPI模…...

统信UOS中使用Vscode编程

写在前面&#xff1a;统信UOS其实就是套壳的Linux系统&#xff0c;所以有问题如果搜不到解决方法&#xff0c;可以参考Linux下的解决方法。 1.环境配置 Vscode : 1.85.0 Vscode就直接下载安装就行&#xff0c;然后安装插件&#xff1a;Volar、中文汉化包 node&#xff1a;18…...

C#从入门到精通(1)

目录 第一章 C#与VS介绍 第二章 第一个C#程序 &#xff08;1&#xff09;C#程序基本组成 1.命名空间 2.类 3.Main方法 4.注释 5.语句 6.标识符及关键字 &#xff08;2&#xff09;程序编写规范 1.代码编写规则 2.程序命名方法 3.元素命名规范 第三章 变量 &…...

openharmony中hilog实证记录说明(3.1和5.0版本)

每次用这个工具hilog都有一些小用法记不清&#xff0c;需要花一些时间去查去分析使用方法&#xff0c;为了给丰富多彩的生活留出更多的时间&#xff0c;所以汇总整理共享来了&#xff0c;它来了它来了~~~~~~~~~ 开始是想通过3.1来汇总的&#xff0c;但实际测试发现openharmony…...

飞书 设计智能字段:通过“字段类型”添加AI功能列

在飞书多维表格中&#xff0c;通过“字段类型”添加AI功能列的核心逻辑是将AI模型能力与结构化数据结合&#xff0c;实现自动化内容生成与信息处理。以下是具体操作步骤及关键要点&#xff0c;结合实际应用场景说明&#xff1a; 一、基础操作步骤 创建多维表格 登录飞书&#x…...

Cannot find module @rollup/rollup-win32-x64-msvc

方法1 在package.json中添加postinstall: "scripts": {"postinstall": "node -e \"const { platform } process; if (platform win32) { require(child_process).execSync(npm install rollup/rollup-win32-x64-msvc, { stdio: inherit });…...

Docker和Dify学习笔记

文章目录 1 docker学习1.1 基本命令使用1.1.1 docker ps查看当前正在运行的镜像1.1.2 docker stop停止容器1.1.3 docker compose容器编排1.1.4 docker网络[1] 进入到容器里面敲命令[2] docker network ls[3] brige网络模式下容器访问宿主机的方式 2 Dify的安装和基础使用2.1 下…...

【AIGC】Win10系统极速部署Docker+Ragflow+Dify

【AIGC】WIN10仅3步部署DockerRagflowDify 一、 Docker快速部署1.F2进入bios界面&#xff0c;按F7设置开启VMX虚拟化技术。保存并退出。2.打开控制面板配置开启服务3.到官网下载docker安装包&#xff0c;一键安装&#xff08;全部默认勾选&#xff09; 二、 RagFlow快速部署1.确…...

Oracle ASM 磁盘组冗余策略

Oracle ASM 磁盘组冗余策略 1. 外部冗余&#xff08;External Redundancy&#xff09;2. 普通冗余&#xff08;Normal Redundancy&#xff09;3. 高冗余&#xff08;High Redundancy&#xff09;关键注意事项如何选择合适的策略&#xff1f; Oracle ASM&#xff08;Automatic S…...

C++ 数据结构

C++ 数据结构 概述 C++作为一种强大的编程语言,在软件开发领域有着广泛的应用。数据结构作为C++编程中不可或缺的一部分,它决定了程序的性能和效率。本文将详细介绍C++中的常见数据结构,包括其定义、特点以及在实际应用中的使用方法。 常见数据结构 1. 数组 数组是一种…...

Unity NodeCanvas AI使用笔记

扩展: 1. 输入输出参数限制&#xff0c;增加描述&#xff0c;根据接口判断类型限制 2.选择节点&#xff0c;遍历节点&#xff0c;行为节点 3.行为节点 行为执行的时候有互斥关系&#xff0c;加入一个queue&#xff0c;最后执行 4.NodeCanvas的参数传参可以由上个节点传到下个节…...