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 方法,關閉數據庫連接,釋放資源。

通過這些注釋,你可以更清晰地理解代碼的邏輯和功能,便于在項目中使用和維護。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/74023.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/74023.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/74023.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

群體智能優化算法-粒子群優化算法(Particle Swarm Optimization, PSO,含Matlab源代碼)

摘要&#xff08;Abstract&#xff09; 粒子群優化&#xff08;PSO&#xff09;是一種基于群體智能的優化算法&#xff0c;受鳥群覓食行為的啟發。PSO 通過模擬粒子&#xff08;個體&#xff09;在搜索空間中的運動來尋找最優解。每個粒子根據自身的歷史最優位置&#xff08;p…

Redis 在windows下的下載安裝與配置

參考鏈接:https://developer.aliyun.com/article/1395346 下載 Redis 訪問 Redis 下載地址&#xff1a;https://github.com/tporadowski/redis/releases 下載 Redis 時&#xff0c;你可以選擇 ZIP 包或 MSI 安裝&#xff1a; ZIP包&#xff1a;需要手動解壓、初始化、配置和…

UE5材質法線強度控制節點FlattenNormal

連法 FlattenNormal內部是這樣的 FlattenNormal的作用是用來調整法線強度 連上FlattenNormal后 拉高數值

在 Elasticsearch 中探索基于 NVIDIA 的 GPU 加速向量搜索

作者&#xff1a;來自 Elastic Chris Hegarty 及 Hemant Malik 由 NVIDIA cuVS 提供支持&#xff0c;此次合作旨在為開發者在 Elasticsearch 中的向量搜索提供 GPU 加速。 在 Elastic Engineering 組織內&#xff0c;我們一直致力于優化向量數據庫的性能。我們的使命是讓 Lucen…

Android 13深度定制:SystemUI狀態欄時間居中顯示終極實戰指南

一、架構設計與技術解析 1. SystemUI狀態欄核心布局機制 層級結構 mermaid 復制 graph TDPhoneStatusBarView --> StatusBarContents[status_bar_contents]StatusBarContents --> LeftLayout[status_bar_left_side]StatusBarContents --> ClockLayout[Clock控件]Left…

ArcGIS10.X影像智能下載!遷移ArcGIS Pro批量智能高清影像下載工具至ArcGIS!

上周我們分享了 我寫的一個ArcGIS Pro版批量下載高清影像&#xff08;谷歌、天地圖、ESRI等&#xff09;工具給大家&#xff0c;Deepseek我&#xff01;寫一個ArcGIS Pro批量下載高清影像&#xff08;谷歌、天地圖、ESRI等&#xff09;工具給大家-CSDN博客文章瀏覽閱讀130次。深…

前端面經分享(25/03/19)

北京一家做協同辦公軟件出海的公司&#xff0c;技術一面&#xff0c;20k-40k&#xff0c;要求3-5年 詳細聊了一下上家公司的項目上家公司的項目是不做了嗎&#xff0c;離職原因是什么&#xff0c;你覺得公司的這個產品怎么樣在做AI類的業務時&#xff0c;作為前端感覺跟常規業務…

7 款可視化爬蟲工具全解析:案例示范與操作指南

目錄 1. ParseHub 2.WebHarvy 3.DataMiner 4.Dexi.io 5.ContentGrabber 6.Portia 7.UiPath 文檔聚焦 7 款熱門可視化爬蟲工具&#xff0c;突出簡便的可視化操作&#xff0c;簡單拖拽、設置&#xff0c;無需編程知識&#xff0c;人人皆可上手。 1. ParseHub ParseHub 是一…

使用 `pytest` 框架時,可以通過極限封裝將 YAML 文件的讀取、解析

在使用 pytest 框架時,可以通過極限封裝將 YAML 文件的讀取、解析和測試用例的通用邏輯封裝成共享的方法或 fixture,從而減少重復代碼。以下是詳細的實現步驟和示例。 1. 封裝 YAML 文件讀取和解析 將 YAML 文件的讀取和解析邏輯封裝到一個工具函數中,供所有測試用例調用。…

HarmonyOS next性能優化:多維度策略與實戰案例

HarmonyOS next性能優化&#xff1a;多維度策略與實戰案例 在HarmonyOS next開發中&#xff0c;性能優化是提升用戶體驗、確保應用流暢運行的關鍵。本文將從多個角度探討HarmonyOS next的性能優化策略&#xff0c;并通過示例代碼展示優化前后的效果對比&#xff0c;幫助開發者…

springboot項目,mapper.xml里面,jdbcType報錯 已解決

找了很多資料&#xff0c;最后發現原來是依賴版本不兼容的問題。改了版本號即可 報錯原因&#xff1a; springboot版本為2.16.3 但是我導入的依賴版本是3.0.1&#xff0c;不兼容&#xff0c;報錯 解決&#xff1a;修改版本號&#xff0c;2.3.1兼容springboot2.6.x。依賴下載完…

rust學習筆記16-206.反轉鏈表(遞歸)

rust函數遞歸在14中已經提到&#xff0c;接下來我們把206.反轉鏈表&#xff0c;用遞歸法實現 遞歸函數通常包含兩個主要部分&#xff1a; 基準條件&#xff08;Base Case&#xff09;&#xff1a;遞歸終止的條件&#xff0c;避免無限遞歸。 遞歸步驟&#xff08;Recursive Ste…

QT-LINUX-Bluetooth藍牙開發

BlueToothAPI QT-BlueToothApi Qt Bluetooth 6.8.2 官方提供的藍牙API不支持linux。 D-Bus的API實現藍牙 確保系統中安裝了 BlueZ(版本需≥5.56),并且 Qt 已正確安裝并配置了 D-Bus 支持。 默默看了下自己的版本.....D-BUS的API也不支持。 在 D-Bus 中,org 目錄是 D-Bus…

鴻蒙Next開發與未來發展的變革:全場景操作系統的全新紀元

文章目錄 引言&#xff1a;從兼容到自主的跨越式進化一、鴻蒙Next技術架構解析1.1 系統架構全景圖1.1.1 微內核架構優勢 1.2 與OpenHarmony的關系 二、開發范式革命2.1 應用開發模式對比2.1.1 元服務&#xff08;Meta Service&#xff09;定義 2.2 開發工具鏈升級&#xff08;D…

【docker】--- 詳解 WSL2 中的 Ubuntu 和 Docker Desktop 的區別和關系!

在編程的藝術世界里,代碼和靈感需要尋找到最佳的交融點,才能打造出令人為之驚嘆的作品。而在這座秋知葉i博客的殿堂里,我們將共同追尋這種完美結合,為未來的世界留下屬于我們的獨特印記。【WSL 】--- Windows11 遷移 WSL 超詳細指南 —— 給室友換一個宿舍! 開發環境一、引…

利用Python爬蟲獲取Shopee(蝦皮)商品詳情:實戰指南

在跨境電商領域&#xff0c;Shopee&#xff08;蝦皮&#xff09;作為東南亞及臺灣地區領先的電商平臺&#xff0c;擁有海量的商品信息。無論是進行市場調研、數據分析&#xff0c;還是尋找熱門商品&#xff0c;獲取Shopee商品詳情都是一項極具價值的任務。然而&#xff0c;手動…

【OCR】總結github上開源 OCR 工具:讓文字識別更簡單

前言 在數字化的時代&#xff0c;光學字符識別&#xff08;OCR&#xff09;技術成為了我們處理文檔、圖像文字信息的得力助手。它能夠將圖像中的文字信息轉換為可編輯和可處理的文本數據&#xff0c;極大地提高了信息處理的效率。今天&#xff0c;我要給大家介紹一些優秀的開源…

GenICam標準

GenICam的目標是為所有類型的相機提供一個統一的編程接口。無論相機使用的是哪種傳輸協議或實現了哪些功能&#xff0c;編程接口&#xff08;API&#xff09;都是一樣的。 GenICam&#xff08;Generic Interface for Cameras&#xff09;是一個為工業相機和圖像采集設備設計的…

Docker學習筆記(十)搭建Docker私有倉庫

一、環境配置 1、宿主機系統&#xff1a;macOS Sequoia(版本15.2) 2、虛擬機VMware Fusion版本&#xff1a;專業版 13.6.2 (24409261) 3、虛擬機系統&#xff1a;AlmaLinux-9-latest-x86_64-boot.iso 二、安裝Harbor開源企業級Docker鏡像 Harbor 是一個開源的企業級 Docker…

關于微信小程序端base64解碼問題

由于atob是瀏覽器端的&#xff0c;對于微信小程序不支持&#xff0c;導致模擬器【開發工具】顯示正常&#xff0c;但真機異常解析失敗問題&#xff0c;微信小程序原有的api&#xff0c;官方文檔中也廢棄了 解決方案&#xff1a; 調用&#xff1a; const decodedString ba…