Hive Local Storage trong Flutter

How to save a custom model in local storage using Hive along with Flutter  and perform CRUD operations. | by Saad Saleem | Medium

1. Tổng quan về Hive Local Storage

Hive là một cơ sở dữ liệu NoSQL dạng key-value được viết bằng Dart, thường được sử dụng trong các ứng dụng Flutter để lưu trữ dữ liệu trực tiếp trên thiết bị. Hive cho phép ứng dụng đọc, ghi, cập nhật và xóa dữ liệu mà không cần gửi yêu cầu đến máy chủ hoặc sử dụng kết nối Internet.

Trong Flutter, Hive được sử dụng để xây dựng chức năng lưu trữ cục bộ (Local Storage), giúp ứng dụng duy trì dữ liệu giữa các lần mở ứng dụng. Ví dụ, ứng dụng có thể lưu thông tin người dùng, cài đặt giao diện, danh sách yêu thích, giỏ hàng hoặc dữ liệu cần sử dụng khi thiết bị ngoại tuyến.

Hive hoạt động theo mô hình key-value, trong đó mỗi dữ liệu được lưu trữ và truy xuất thông qua một khóa (Key) tương ứng với giá trị (Value). Cách tổ chức này tương đối đơn giản, dễ sử dụng và phù hợp với những ứng dụng cần lưu trữ dữ liệu có cấu trúc không quá phức tạp.

Hive không yêu cầu một máy chủ cơ sở dữ liệu riêng. Dữ liệu được lưu trên bộ nhớ của thiết bị, thường trong thư mục dữ liệu riêng của ứng dụng. Điều này giúp giảm độ trễ khi truy xuất dữ liệu và hạn chế việc phải thực hiện các yêu cầu mạng đối với những thông tin có thể xử lý hoàn toàn ở phía thiết bị.

Một điểm quan trọng cần phân biệt là Hive và Hive Local Storage không phải hai công nghệ hoàn toàn riêng biệt. Hive là thư viện lưu trữ dữ liệu, còn Hive Local Storage là cách sử dụng Hive để triển khai chức năng lưu trữ cục bộ trong ứng dụng.

2. Kiến trúc lưu trữ của Hive

Hive tổ chức dữ liệu thông qua các thành phần chính, bao gồm Box, Key, Value, Adapter và cơ chế tuần tự hóa dữ liệu.

2.1. Box

Box là thành phần trung tâm trong Hive, đóng vai trò như một vùng lưu trữ dữ liệu. Có thể hình dung Box tương tự một bảng dữ liệu trong cơ sở dữ liệu quan hệ, mặc dù cách tổ chức và truy vấn dữ liệu của hai hệ thống khác nhau.

Một ứng dụng Flutter có thể tạo nhiều Box để phân chia dữ liệu theo chức năng.

Ví dụ:

Box Dữ liệu lưu trữ
settingsBox Cài đặt ứng dụng
userBox Thông tin người dùng
cartBox Sản phẩm trong giỏ hàng
favoritesBox Danh sách sản phẩm yêu thích
cacheBox Dữ liệu tạm được lưu để sử dụng lại

Việc chia dữ liệu thành nhiều Box giúp mã nguồn rõ ràng, dễ quản lý và thuận tiện hơn khi cần thay đổi cấu trúc dữ liệu.

Hive cung cấp hai cách sử dụng phổ biến:

Box thông thường: Phù hợp với phần lớn dữ liệu có thể tải và quản lý trong bộ nhớ.

LazyBox: Dữ liệu được đọc từ bộ nhớ lưu trữ khi cần truy cập, thay vì tải toàn bộ giá trị vào bộ nhớ ngay từ đầu. LazyBox phù hợp với những tập dữ liệu lớn hoặc trường hợp ứng dụng không thường xuyên sử dụng tất cả các bản ghi.

2.2. Key và Value

Key là khóa định danh được sử dụng để truy xuất dữ liệu, trong khi Value là giá trị tương ứng được lưu trữ.

Ví dụ:

await settingsBox.put('theme', 'dark');
await settingsBox.put('language', 'vi');
await settingsBox.put('fontSize', 16);

Trong ví dụ trên:

  • theme là Key, còn dark là Value.

  • language là Key, còn vi là Value.

  • fontSize là Key, còn 16 là Value.

Để đọc dữ liệu, ứng dụng sử dụng khóa tương ứng:

final theme = settingsBox.get('theme');
final language = settingsBox.get('language');
final fontSize = settingsBox.get('fontSize');

Nếu khóa chưa tồn tại, kết quả thường là null, trừ khi lập trình viên cung cấp giá trị mặc định thông qua tham số defaultValue.

final theme = settingsBox.get(
  'theme',
  defaultValue: 'light',
);

Cách lưu trữ này đặc biệt hữu ích khi ứng dụng cần ghi nhớ trạng thái hoặc cấu hình mà người dùng đã lựa chọn.

2.3. Adapter và dữ liệu đối tượng

Ngoài các kiểu dữ liệu cơ bản, ứng dụng còn có thể cần lưu những đối tượng phức tạp như thông tin người dùng, sản phẩm, bài tập hoặc hóa đơn.

Hive hỗ trợ lưu các đối tượng Dart thông qua cơ chế chuyển đổi dữ liệu, thường được triển khai bằng TypeAdapter. Adapter chịu trách nhiệm chuyển đổi đối tượng thành dạng dữ liệu có thể lưu trữ và khôi phục đối tượng khi đọc dữ liệu.

Ví dụ, một đối tượng sản phẩm có thể chứa:

class Product {
  final String name;
  final double price;
  final int quantity;

  Product({
    required this.name,
    required this.price,
    required this.quantity,
  });
}

Để lưu đối tượng này bằng Hive theo cách sử dụng TypeAdapter, cần đăng ký adapter tương ứng và bảo đảm lớp dữ liệu được định nghĩa theo phiên bản Hive đang sử dụng.

Khi đã có adapter, ứng dụng có thể lưu trực tiếp đối tượng thay vì phải tự chuyển từng thuộc tính thành chuỗi JSON.

Đối với Hive 2.x, TypeAdapter thường được khai báo bằng @HiveType và @HiveField, sau đó tạo mã chuyển đổi bằng công cụ sinh mã. Với Hive CE hoặc các phiên bản khác, API và quy trình cấu hình có thể khác nhau.

2.4. Cơ chế tuần tự hóa dữ liệu

Tuần tự hóa (Serialization) là quá trình chuyển đổi dữ liệu trong bộ nhớ thành dạng có thể lưu trữ. Quá trình ngược lại được gọi là giải tuần tự hóa (Deserialization).

Ví dụ, khi ứng dụng lưu thông tin người dùng, dữ liệu đang tồn tại dưới dạng đối tượng Dart cần được chuyển đổi sang dạng mà Hive có thể ghi xuống bộ nhớ. Khi người dùng mở ứng dụng lần tiếp theo, dữ liệu được đọc và khôi phục để tiếp tục sử dụng.

Đối với kiểu dữ liệu cơ bản, Hive hỗ trợ nhiều kiểu dữ liệu phổ biến mà không cần lập trình viên tự viết adapter. Với kiểu dữ liệu tùy chỉnh, cần có cơ chế chuyển đổi tương ứng.

Cơ chế này giúp dữ liệu được lưu trữ nhất quán và giảm lượng mã xử lý thủ công trong ứng dụng.

3. Đặc điểm nổi bật của Hive Local Storage

3.1. Tốc độ truy xuất dữ liệu nhanh

Hive được thiết kế để thực hiện các thao tác đọc và ghi dữ liệu cục bộ với chi phí xử lý thấp. Khi dữ liệu đã sẵn sàng trong bộ nhớ, ứng dụng có thể truy xuất thông qua Key mà không cần thực hiện truy vấn đến máy chủ bên ngoài.

Điều này giúp giảm độ trễ đối với những tính năng cần phản hồi nhanh, chẳng hạn như hiển thị tùy chọn giao diện, tải danh sách yêu thích hoặc lấy thông tin giỏ hàng đã lưu.

Tuy nhiên, hiệu năng thực tế còn phụ thuộc vào kích thước dữ liệu, số lượng thao tác, loại Box và cách thiết kế ứng dụng.

3.2. Hoạt động ngoại tuyến

Hive lưu dữ liệu trực tiếp trên thiết bị, do đó các dữ liệu đã được lưu có thể tiếp tục được sử dụng khi không có Internet.

Ví dụ, một ứng dụng quản lý phòng gym có thể lưu thông tin buổi tập gần nhất, lịch sử bài tập đã đồng bộ hoặc các thiết lập cá nhân. Người dùng vẫn có thể xem những dữ liệu có sẵn ngay cả khi kết nối mạng bị gián đoạn.

Tuy nhiên, Hive không tự động đồng bộ dữ liệu giữa các thiết bị. Nếu người dùng đăng nhập cùng một tài khoản trên điện thoại và máy tính bảng, dữ liệu trên hai thiết bị sẽ không tự cập nhật cho nhau nếu ứng dụng không triển khai cơ chế đồng bộ riêng.

3.3. Không cần máy chủ cơ sở dữ liệu riêng

Hive không yêu cầu triển khai máy chủ cơ sở dữ liệu như cách một ứng dụng sử dụng PostgreSQL hoặc MySQL.

Điều này giúp giảm độ phức tạp khi xây dựng những ứng dụng Flutter có nhu cầu lưu dữ liệu cục bộ đơn giản, đồng thời giảm số lượng thành phần cần cấu hình và vận hành.

Dù vậy, các ứng dụng có hệ thống tài khoản, phân quyền, giao dịch hoặc dữ liệu dùng chung giữa nhiều người dùng vẫn thường cần một backend để xử lý dữ liệu trung tâm.

3.4. Hỗ trợ lập trình bất đồng bộ

Các thao tác đọc và ghi dữ liệu có thể được thực hiện thông qua những API bất đồng bộ, đặc biệt khi mở Box hoặc ghi dữ liệu xuống bộ nhớ.

Ví dụ:

await box.put('username', 'Tien');

Từ khóa await giúp chương trình chờ thao tác hoàn thành trước khi tiếp tục thực hiện những bước phụ thuộc vào kết quả đó.

Trong Flutter, việc sử dụng API bất đồng bộ đúng cách giúp quản lý luồng xử lý rõ ràng và tránh thực hiện các thao tác phụ thuộc dữ liệu quá sớm.

Lưu ý rằng không phải mọi thao tác đọc dữ liệu của Hive đều bất đồng bộ. Box thông thường có thể cung cấp dữ liệu trực tiếp sau khi đã được mở, trong khi LazyBox sử dụng API đọc bất đồng bộ.

3.5. Tổ chức dữ liệu linh hoạt

Hive phù hợp với cách lưu trữ dữ liệu theo khóa và giá trị. Lập trình viên có thể sử dụng khóa dạng chuỗi hoặc số nguyên tùy theo API và mục đích sử dụng.

Cách tiếp cận này phù hợp với dữ liệu có cấu trúc đơn giản, không cần những truy vấn quan hệ phức tạp.

Tuy nhiên, nếu ứng dụng cần thực hiện nhiều phép JOIN, lọc dữ liệu theo nhiều điều kiện, thống kê phức tạp hoặc duy trì quan hệ giữa nhiều thực thể, một cơ sở dữ liệu quan hệ như SQLite hoặc PostgreSQL có thể phù hợp hơn.

3.6. Giảm sự phụ thuộc vào kết nối mạng

Việc lưu trữ cục bộ giúp ứng dụng hạn chế những yêu cầu mạng không cần thiết.

Chẳng hạn, thay vì tải lại toàn bộ cài đặt người dùng từ máy chủ mỗi lần mở ứng dụng, chương trình có thể đọc cấu hình từ Hive ngay trên thiết bị.

Trong những hệ thống có backend, Hive còn có thể được sử dụng để lưu bộ nhớ đệm (Cache), giúp tăng tốc hiển thị và giảm số lần tải lại dữ liệu. Dữ liệu Cache cần có cơ chế cập nhật hoặc hết hạn phù hợp để tránh hiển thị thông tin lỗi thời.

4. Các loại dữ liệu phù hợp với Hive

Hive có thể được sử dụng trong nhiều tình huống khác nhau tùy theo nhu cầu của ứng dụng.

Nhóm dữ liệu Ví dụ sử dụng
Cài đặt cá nhân Ngôn ngữ, giao diện sáng/tối, cỡ chữ
Trạng thái ứng dụng Tab đang chọn, bộ lọc gần nhất
Dữ liệu yêu thích Danh sách sản phẩm hoặc bài viết yêu thích
Giỏ hàng cục bộ Sản phẩm đã thêm vào giỏ nhưng chưa đồng bộ
Cache Danh sách sản phẩm đã tải từ API
Dữ liệu nghiệp vụ nhỏ Danh sách bài tập hoặc ghi chú
Trạng thái đồng bộ Thời điểm tải dữ liệu gần nhất, trạng thái cần đồng bộ

Đối với thông tin nhạy cảm như mật khẩu, token xác thực hoặc khóa bí mật, không nên mặc định xem Hive là kho lưu trữ an toàn. Cần đánh giá mô hình đe dọa và sử dụng giải pháp bảo mật phù hợp, chẳng hạn Keychain trên iOS hoặc Keystore trên Android thông qua thư viện chuyên dụng.

5. Cài đặt Hive trong dự án Flutter

Để sử dụng Hive, lập trình viên cần thêm thư viện phù hợp vào dự án và khởi tạo hệ thống lưu trữ trước khi thực hiện các thao tác đọc, ghi.

Hive có nhiều biến thể và phiên bản, vì vậy cần xác định chính xác thư viện đang dùng trước khi áp dụng hướng dẫn cài đặt.

5.1. Lựa chọn phiên bản thư viện

Hai hướng triển khai thường gặp là:

  • Hive 2.x: Sử dụng API truyền thống của Hive, thường đi kèm hive_flutter trong ứng dụng Flutter.

  • Hive CE: Một nhánh phát triển tiếp nối hệ sinh thái Hive, có các khác biệt về gói thư viện và API tùy phiên bản.

Đối với dự án hiện có, nên kiểm tra phiên bản Flutter, Dart và các package trong pubspec.yaml để chọn hướng triển khai tương thích. Không nên trộn API của nhiều nhánh thư viện trong cùng một ví dụ.

5.2. Khởi tạo Hive

Ví dụ dưới đây minh họa cách khởi tạo theo API Hive 2.x với hive_flutter.

Cài đặt các package cần thiết:

flutter pub add hive
flutter pub add hive_flutter

Sau đó, cấu hình trong tệp main.dart:

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Hive.initFlutter();

  await Hive.openBox('settings');

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('Hive Local Storage'),
        ),
      ),
    );
  }
}

Trong đoạn code trên:

  1. WidgetsFlutterBinding.ensureInitialized() bảo đảm Flutter binding được khởi tạo trước khi thực hiện những thao tác cần môi trường Flutter.

  2. Hive.initFlutter() khởi tạo Hive với thư mục lưu trữ phù hợp trên thiết bị.

  3. Hive.openBox('settings') mở Box có tên settings.

  4. runApp() khởi chạy giao diện ứng dụng sau khi Box đã được mở.

Việc mở Box trước khi chạy ứng dụng giúp những màn hình cần sử dụng dữ liệu có thể truy cập Box ngay khi được khởi tạo.

6. Các thao tác CRUD với Hive

CRUD là viết tắt của Create, Read, Update và Delete, đại diện cho bốn thao tác cơ bản trong quản lý dữ liệu.

6.1. Create – Thêm dữ liệu

Để thêm dữ liệu vào Hive, sử dụng phương thức put() hoặc add().

final box = Hive.box('settings');

await box.put('username', 'Tien');
await box.put('theme', 'dark');

await box.add('Giá trị mới');

Phương thức put() lưu giá trị theo một Key cụ thể. Nếu Key đã tồn tại, giá trị tương ứng sẽ được thay thế.

Phương thức add() thêm một giá trị mới và để Hive tự cấp khóa theo cơ chế của Box.

Đối với những dữ liệu cần truy xuất bằng tên định danh rõ ràng, put() thường dễ quản lý hơn.

6.2. Read – Đọc dữ liệu

Để đọc dữ liệu, sử dụng phương thức get().

final box = Hive.box('settings');

final username = box.get(
  'username',
  defaultValue: 'Guest',
);

final theme = box.get(
  'theme',
  defaultValue: 'light',
);

print(username);
print(theme);

Nếu Key tồn tại, Hive trả về giá trị đã lưu. Nếu Key không tồn tại, ứng dụng có thể sử dụng giá trị mặc định được truyền vào defaultValue.

Đây là cách hữu ích để thiết lập cấu hình ban đầu khi người dùng mới cài đặt ứng dụng.

6.3. Update – Cập nhật dữ liệu

Để cập nhật một giá trị đã lưu, sử dụng lại phương thức put() với cùng Key.

final box = Hive.box('settings');

await box.put('theme', 'light');

Nếu trước đó theme có giá trị dark, giá trị sẽ được thay đổi thành light.

Đối với đối tượng có nhiều thuộc tính, cần cập nhật đối tượng và lưu lại vào Box theo cách phù hợp với mô hình dữ liệu. Việc thay đổi một thuộc tính trong bộ nhớ không nên được mặc định là đã tự động ghi lại toàn bộ đối tượng xuống bộ lưu trữ.

6.4. Delete – Xóa dữ liệu

Để xóa một bản ghi theo Key, sử dụng delete().

final box = Hive.box('settings');

await box.delete('theme');

Để xóa toàn bộ dữ liệu trong Box, có thể sử dụng:

await box.clear();

Hai thao tác này có phạm vi khác nhau. delete() chỉ xóa giá trị được xác định bởi Key, trong khi clear() xóa toàn bộ dữ liệu của Box. Vì vậy, cần lựa chọn đúng thao tác để tránh làm mất những dữ liệu không mong muốn.

7. Theo dõi thay đổi dữ liệu trong giao diện Flutter

Một ứng dụng thực tế thường cần cập nhật giao diện ngay sau khi dữ liệu thay đổi. Ví dụ, khi người dùng chuyển giao diện từ sáng sang tối, ứng dụng cần phản ánh trạng thái mới trên màn hình.

Hive hỗ trợ theo dõi thay đổi thông qua các sự kiện của Box. Trong Flutter, có thể sử dụng ValueListenableBuilder kết hợp với box.listenable() để xây dựng giao diện phản ứng theo dữ liệu.

Ví dụ:

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

class ThemeSettings extends StatelessWidget {
  const ThemeSettings({super.key});

  @override
  Widget build(BuildContext context) {
    final box = Hive.box('settings');

    return ValueListenableBuilder(
      valueListenable: box.listenable(
        keys: ['theme'],
      ),
      builder: (context, Box box, _) {
        final theme = box.get(
          'theme',
          defaultValue: 'light',
        );

        return SwitchListTile(
          title: const Text('Dark mode'),
          value: theme == 'dark',
          onChanged: (enabled) async {
            await box.put(
              'theme',
              enabled ? 'dark' : 'light',
            );
          },
        );
      },
    );
  }
}

Trong ví dụ này, ValueListenableBuilder lắng nghe những thay đổi của Key theme. Khi người dùng thay đổi trạng thái, ứng dụng ghi giá trị mới vào Hive và giao diện được xây dựng lại dựa trên dữ liệu mới.

Cách tiếp cận này giúp tách biệt dữ liệu và giao diện, đồng thời hạn chế việc phải quản lý trạng thái thủ công trong những tình huống đơn giản.

Lưu ý: Ví dụ sử dụng API của Hive 2.x và hive_flutter. Nếu dự án sử dụng Hive CE hoặc phiên bản có API khác, cần điều chỉnh phần import và cấu hình tương ứng.

8. Lưu trữ dữ liệu dạng đối tượng trong Hive

Trong ứng dụng thực tế, dữ liệu thường được biểu diễn dưới dạng các đối tượng có nhiều thuộc tính. Chẳng hạn, một ứng dụng thương mại điện tử có thể cần lưu sản phẩm với tên, giá bán, số lượng và trạng thái yêu thích.

Với Hive 2.x, một lớp dữ liệu có thể được khai báo bằng các annotation như sau:

import 'package:hive/hive.dart';

part 'product.g.dart';

@HiveType(typeId: 0)
class Product {
  @HiveField(0)
  final String name;

  @HiveField(1)
  final double price;

  @HiveField(2)
  final int quantity;

  Product({
    required this.name,
    required this.price,
    required this.quantity,
  });
}

Trong ví dụ trên:

  • @HiveType đánh dấu lớp dữ liệu cần được lưu bằng Hive.

  • typeId xác định loại đối tượng và phải được quản lý nhất quán trong dự án.

  • @HiveField đánh dấu các trường dữ liệu được lưu trữ.

  • part 'product.g.dart' tham chiếu đến tệp mã được sinh tự động.

Sau khi cài đặt thêm công cụ sinh mã phù hợp với phiên bản đang dùng, lập trình viên tạo adapter bằng lệnh:

dart run build_runner build --delete-conflicting-outputs

Tiếp theo, đăng ký adapter và mở Box:

await Hive.initFlutter();

Hive.registerAdapter(ProductAdapter());

await Hive.openBox<Product>('products');

Khi đó, ứng dụng có thể lưu đối tượng sản phẩm:

final productBox = Hive.box<Product>('products');

await productBox.put(
  'product_001',
  Product(
    name: 'Wireless Mouse',
    price: 350000,
    quantity: 2,
  ),
);

Để đọc đối tượng:

final product = productBox.get('product_001');

if (product != null) {
  print(product.name);
  print(product.price);
  print(product.quantity);
}

Ví dụ này cho thấy Hive không chỉ lưu được những giá trị đơn giản mà còn có thể quản lý các đối tượng Dart có cấu trúc rõ ràng.

Khi thay đổi cấu trúc lớp dữ liệu đã được sử dụng trong các phiên bản ứng dụng trước đó, cần chú ý khả năng tương thích dữ liệu và cách nâng cấp schema để tránh lỗi đọc dữ liệu cũ.

9. Ứng dụng Hive trong các dự án Flutter thực tế

9.1. Ứng dụng thương mại điện tử

Trong ứng dụng bán hàng, Hive có thể lưu danh sách sản phẩm yêu thích, nội dung giỏ hàng, bộ lọc tìm kiếm gần nhất và dữ liệu sản phẩm đã tải.

Khi người dùng thêm một sản phẩm vào danh sách yêu thích, ứng dụng có thể lưu trạng thái đó cục bộ để người dùng vẫn xem được danh sách đã lưu khi mở ứng dụng lần tiếp theo.

Nếu ứng dụng có backend, dữ liệu cục bộ cần được đồng bộ khi thích hợp. Đặc biệt, giá bán, tồn kho và trạng thái đơn hàng cần được xác nhận từ máy chủ thay vì chỉ dựa vào dữ liệu lưu trên thiết bị.

9.2. Ứng dụng quản lý phòng gym

Đối với ứng dụng quản lý phòng gym, Hive có thể lưu những thông tin phục vụ trải nghiệm người dùng như lịch tập gần đây, các bài tập yêu thích, bộ lọc bài tập hoặc trạng thái giao diện.

Trong trường hợp người dùng tập luyện ở nơi kết nối Internet không ổn định, ứng dụng có thể giữ lại một số dữ liệu đã tải trước đó để tiếp tục hiển thị.

Tuy nhiên, thông tin quan trọng như trạng thái hội viên, thời hạn gói tập và dữ liệu điểm danh chính thức nên được xác minh với backend để bảo đảm tính chính xác và hạn chế việc sửa đổi dữ liệu từ phía thiết bị.

9.3. Ứng dụng ghi chú và quản lý công việc

Ứng dụng ghi chú có thể sử dụng Hive để lưu nội dung ghi chú, danh sách công việc, trạng thái hoàn thành và những thiết lập cá nhân.

Khi người dùng tạo một ghi chú mới, dữ liệu được lưu ngay trên thiết bị, giúp ứng dụng có thể truy xuất lại nội dung trong những lần mở tiếp theo.

Nếu ứng dụng cần đồng bộ ghi chú giữa nhiều thiết bị, lập trình viên phải xây dựng thêm cơ chế đồng bộ với máy chủ hoặc một dịch vụ lưu trữ phù hợp.

9.4. Ứng dụng học tập

Trong ứng dụng học tập, Hive có thể lưu tiến độ học, bài học đã xem, câu hỏi đã đánh dấu và trạng thái hoàn thành từng nội dung.

Nhờ vậy, người dùng có thể tiếp tục học từ vị trí gần nhất mà không cần tải lại toàn bộ trạng thái từ máy chủ mỗi lần mở ứng dụng.

Với những dữ liệu có tính chất cá nhân hoặc quan trọng, ứng dụng nên có cơ chế sao lưu hoặc đồng bộ để tránh mất dữ liệu khi người dùng gỡ cài đặt hoặc thay đổi thiết bị.

10. So sánh Hive với SharedPreferences, SQLite và các giải pháp lưu trữ khác

Trong Flutter, không có một giải pháp Local Storage phù hợp với mọi loại dữ liệu. Việc lựa chọn cần dựa trên độ phức tạp của dữ liệu, yêu cầu truy vấn và mục đích sử dụng.

Tiêu chí Hive SharedPreferences SQLite
Mục đích chính Lưu trữ dữ liệu key-value và đối tượng Lưu cài đặt đơn giản Cơ sở dữ liệu quan hệ
Dữ liệu phù hợp Danh sách, đối tượng, Cache Boolean, số, chuỗi cấu hình Bản ghi có quan hệ
Truy vấn phức tạp Hạn chế Không phù hợp Hỗ trợ SQL
Quan hệ giữa bảng Không phải thế mạnh Không hỗ trợ Hỗ trợ
Sử dụng ngoại tuyến Có Có Có
Thiết lập Tương đối đơn giản Đơn giản Cần thiết kế schema
Trường hợp tiêu biểu Giỏ hàng, yêu thích, Cache Chế độ tối, ngôn ngữ Quản lý dữ liệu có quan hệ

Ngoài ra, Flutter còn có thể sử dụng những giải pháp khác như Isar, ObjectBox hoặc các thư viện dựa trên SQLite. Mỗi lựa chọn có đặc điểm riêng về hiệu năng, API, khả năng truy vấn và mức độ hỗ trợ.

SharedPreferences thích hợp khi ứng dụng chỉ cần ghi nhớ một vài tùy chọn đơn giản. Không nên dùng nó như một cơ sở dữ liệu để quản lý danh sách đối tượng lớn.

Hive phù hợp với dữ liệu cục bộ dạng key-value hoặc đối tượng khi ứng dụng không cần nhiều truy vấn quan hệ phức tạp.

SQLite thích hợp với những hệ thống cần truy vấn dữ liệu có cấu trúc, quan hệ giữa các bảng và các thao tác SQL.

Việc lựa chọn nên dựa trên yêu cầu thực tế của dự án thay vì chỉ dựa vào tốc độ hoặc mức độ phổ biến của thư viện.

11. Ưu điểm của Hive Local Storage

Hive mang lại nhiều lợi ích khi được sử dụng đúng mục đích trong ứng dụng Flutter.

Thứ nhất, dễ tích hợp với Dart và Flutter. API tương đối dễ tiếp cận, giúp lập trình viên triển khai các thao tác lưu trữ mà không cần viết nhiều mã xử lý cơ sở dữ liệu.

Thứ hai, truy xuất dữ liệu cục bộ thuận tiện. Việc đọc dữ liệu thông qua Key giúp các thao tác lấy thông tin đơn giản và dễ tổ chức.

Thứ ba, hỗ trợ dữ liệu có cấu trúc. Ngoài những kiểu dữ liệu cơ bản, Hive có thể lưu đối tượng Dart thông qua adapter tương ứng.

Thứ tư, hỗ trợ ứng dụng ngoại tuyến. Dữ liệu đã được lưu trên thiết bị có thể tiếp tục được sử dụng khi không có kết nối mạng.

Thứ năm, phù hợp với cơ chế Cache. Ứng dụng có thể lưu dữ liệu đã tải để cải thiện trải nghiệm sử dụng và hạn chế những yêu cầu mạng lặp lại.

Thứ sáu, giảm sự phụ thuộc vào backend đối với dữ liệu cục bộ. Những cài đặt cá nhân hoặc dữ liệu không cần chia sẻ giữa nhiều người dùng có thể được quản lý trực tiếp trên thiết bị.

12. Hạn chế và những lưu ý khi sử dụng Hive

Bên cạnh những ưu điểm, Hive cũng có một số giới hạn cần được cân nhắc trong quá trình phát triển.

12.1. Khả năng truy vấn hạn chế

Hive không được thiết kế để thay thế hoàn toàn cơ sở dữ liệu quan hệ. Những truy vấn nhiều điều kiện, phép JOIN hoặc thống kê phức tạp có thể khó triển khai hơn so với SQL.

Đối với các hệ thống có nhiều thực thể và quan hệ dữ liệu, cần đánh giá kỹ trước khi chọn Hive làm giải pháp lưu trữ chính.

12.2. Không tự động đồng bộ giữa các thiết bị

Dữ liệu trong Hive được lưu trên thiết bị hiện tại. Thay đổi trên thiết bị này không tự động xuất hiện trên thiết bị khác.

Nếu cần đồng bộ dữ liệu, ứng dụng phải triển khai thêm API, backend hoặc dịch vụ đồng bộ. Ngoài ra, cần xử lý xung đột khi cùng một dữ liệu được chỉnh sửa ở nhiều nơi.

12.3. Rủi ro mất dữ liệu cục bộ

Dữ liệu có thể bị mất khi người dùng xóa dữ liệu ứng dụng, gỡ cài đặt hoặc khi thiết bị gặp sự cố lưu trữ.

Do đó, với những dữ liệu quan trọng, nên có cơ chế sao lưu hoặc đồng bộ lên máy chủ.

12.4. Bảo mật dữ liệu

Không nên mặc định dữ liệu lưu trong Hive đã được mã hóa hoặc bảo vệ đầy đủ. Nếu ứng dụng cần lưu dữ liệu nhạy cảm, phải lựa chọn cơ chế bảo vệ phù hợp và kiểm tra khả năng mã hóa của thư viện cũng như phiên bản đang sử dụng.

Không nên lưu mật khẩu dạng văn bản thuần hoặc đặt các khóa bí mật quan trọng trong một Box thông thường.

12.5. Quản lý phiên bản dữ liệu

Khi ứng dụng được cập nhật, cấu trúc dữ liệu có thể thay đổi. Ví dụ, một phiên bản mới bổ sung trường category vào đối tượng sản phẩm.

Nếu không quản lý quá trình chuyển đổi dữ liệu cũ, ứng dụng có thể gặp lỗi khi đọc những bản ghi được lưu bởi phiên bản trước.

Vì vậy, lập trình viên cần thiết kế schema ổn định, quản lý các trường dữ liệu và thực hiện kiểm tra tương thích khi nâng cấp ứng dụng.

12.6. Lựa chọn phiên bản thư viện phù hợp

Hệ sinh thái Hive có nhiều nhánh và phiên bản với sự khác biệt về API, cách cài đặt và công cụ sinh mã.

Trước khi triển khai, cần kiểm tra tài liệu chính thức và khả năng tương thích với phiên bản Dart, Flutter của dự án. Điều này đặc biệt quan trọng khi sử dụng TypeAdapter hoặc nâng cấp một ứng dụng đã có dữ liệu được lưu từ trước.

13. Các nguyên tắc sử dụng Hive hiệu quả

Để xây dựng hệ thống Local Storage ổn định, lập trình viên nên tuân thủ những nguyên tắc sau:

  1. Phân chia Box theo chức năng: Tổ chức dữ liệu thành những vùng lưu trữ có mục đích rõ ràng, tránh gom tất cả dữ liệu vào một Box lớn mà không có quy ước.

  2. Đặt Key nhất quán: Sử dụng tên khóa dễ hiểu, có quy tắc đặt tên thống nhất để hạn chế nhầm lẫn giữa các nhóm dữ liệu.

  3. Khởi tạo trước khi sử dụng: Khởi tạo Hive và mở các Box cần thiết trước khi những thành phần phụ thuộc bắt đầu truy cập dữ liệu.

  4. Quản lý kiểu dữ liệu: Xác định rõ kiểu dữ liệu được lưu và sử dụng adapter khi cần quản lý đối tượng tùy chỉnh.

  5. Không lưu dữ liệu nhạy cảm một cách tùy tiện: Đánh giá yêu cầu bảo mật và sử dụng giải pháp chuyên dụng đối với thông tin xác thực hoặc dữ liệu có giá trị cao.

  6. Xây dựng cơ chế đồng bộ khi cần thiết: Nếu dữ liệu phải được chia sẻ giữa nhiều thiết bị, cần thiết kế quy trình đồng bộ và giải quyết xung đột.

  7. Quản lý lỗi: Xử lý các trường hợp mở Box thất bại, dữ liệu không tồn tại hoặc dữ liệu cũ không tương thích với cấu trúc mới.

  8. Kiểm thử các thao tác lưu trữ: Kiểm tra khả năng thêm, đọc, sửa, xóa dữ liệu cũng như hành vi khi ứng dụng khởi động lại.

  9. Chọn đúng công nghệ: Sử dụng Hive cho những trường hợp phù hợp với mô hình key-value, thay vì cố gắng triển khai các truy vấn quan hệ phức tạp bằng một công cụ không được thiết kế cho mục đích đó.

14. Kết luận

Hive Local Storage là một giải pháp lưu trữ dữ liệu cục bộ hữu ích trong quá trình phát triển ứng dụng Flutter. Với mô hình key-value, khả năng quản lý các kiểu dữ liệu cơ bản và hỗ trợ lưu đối tượng Dart thông qua adapter, Hive giúp lập trình viên triển khai những chức năng lưu trữ một cách tương đối đơn giản.

Hive đặc biệt phù hợp với việc quản lý cài đặt cá nhân, dữ liệu yêu thích, giỏ hàng cục bộ, dữ liệu Cache và những thông tin cần sử dụng khi ứng dụng ngoại tuyến. Khi được tổ chức hợp lý, Hive có thể góp phần cải thiện tốc độ truy xuất dữ liệu và trải nghiệm sử dụng ứng dụng.

Tuy nhiên, Hive không thay thế hoàn toàn backend hoặc các cơ sở dữ liệu quan hệ. Những hệ thống cần đồng bộ nhiều thiết bị, quản lý giao dịch, truy vấn phức tạp hoặc bảo vệ dữ liệu quan trọng vẫn cần những giải pháp bổ sung phù hợp.

Tóm lại, Hive Local Storage là lựa chọn đáng cân nhắc khi ứng dụng Flutter cần lưu trữ dữ liệu trực tiếp trên thiết bị với cách tổ chức đơn giản, dễ quản lý và có khả năng hoạt động ngoại tuyến. Việc lựa chọn đúng loại dữ liệu, quản lý phiên bản thư viện và xây dựng cơ chế bảo mật, đồng bộ phù hợp sẽ giúp khai thác hiệu quả Hive trong các dự án thực tế.

Bài viết khác

Riverpod, BLoC và Provider

Riverpod, BLoC và Provider trong Flutter 1. Tổng quan về các giải pháp quản lý trạng thái Trong quá trình phát triển ứng dụng Flutter, State Management là một trong những vấn đề quan trọng cần được giải quyết để đảm bảo dữ liệu được quản lý nhất quán và giao diện được cập nhật […]

State Management

State Management 1. Tổng quan về State Management State Management là kỹ thuật quản lý trạng thái của ứng dụng, đóng vai trò quan trọng trong quá trình phát triển giao diện người dùng bằng Flutter. Kỹ thuật này giúp ứng dụng lưu trữ, cập nhật, chia sẻ và đồng bộ dữ liệu giữa các […]

Navigation & Routing

          Trong quá trình phát triển các ứng dụng web, ứng dụng di động và hệ thống bản đồ số, Navigation và Routing là hai khái niệm giữ vai trò trung tâm. Nếu Navigation tập trung vào cách người dùng di chuyển giữa các màn hình, trang hoặc chức năng, thì […]

Material & Cupertino

     Trong quá trình phát triển ứng dụng di động, giao diện người dùng không chỉ có nhiệm vụ trình bày thông tin mà còn phải tạo ra cảm giác quen thuộc, nhất quán và dễ sử dụng. Người dùng Android thường mong đợi các thành phần giao diện mang phong cách Material Design […]

Smoke Testing(Kiểm thử khói)

Smoke Testing là gì? Trong mô hình phát triển phần mềm hiện đại (dù là Agile, Scrum hay DevOps), tốc độ bàn giao các bản build (xây dựng mã nguồn) diễn ra vô cùng nhanh chóng. Mỗi ngày, đội ngũ lập trình viên có thể chuyển giao từ vài bản build nhỏ đến hàng chục […]

Flutter Layout & Responsive UI

      Trong phát triển ứng dụng hiện đại, giao diện người dùng không chỉ cần đẹp mà còn phải thích ứng tốt với nhiều kích thước màn hình, tỷ lệ khung hình và phương thức tương tác khác nhau. Một ứng dụng có thể được sử dụng trên điện thoại nhỏ, máy tính […]

Leave a Reply

Your email address will not be published. Required fields are marked *