- vừa được xem lúc

Tìm hiểu về SharedPreferences trong Flutter: Lưu trữ dữ liệu cục bộ đơn giản

0 0 3

Người đăng: Coder Tập Sự

Theo Viblo Asia

Sau khi đã nắm vững các kỹ thuật quản lý trạng thái để xử lý dữ liệu trong bộ nhớ (in-memory), chúng ta sẽ cần một phương pháp để lưu trữ dữ liệu bền vững, tức là dữ liệu không bị mất đi khi người dùng đóng ứng dụng. Đây là lúc lưu trữ dữ liệu cục bộ trở nên cần thiết.

Trong Flutter, một trong những cách đơn giản và phổ biến nhất để lưu trữ dữ liệu cục bộ là sử dụng package shared_preferences.


SharedPreferences là gì?

shared_preferences là một package Flutter cho phép chúng ta lưu trữ các cặp khóa-giá trị (key-value pairs) đơn giản trên thiết bị. Nó thường được dùng để lưu trữ:

  • Cài đặt người dùng: Chế độ sáng/tối, ngôn ngữ, tùy chọn thông báo.
  • Trạng thái ứng dụng nhỏ: Ví dụ, trạng thái "đã đăng nhập" của người dùng, hoặc lần đầu mở ứng dụng.
  • Dữ liệu nhỏ, không phức tạp: Ví dụ, điểm số cao trong một trò chơi, tên người dùng gần đây.

Về cơ bản, shared_preferences sử dụng các API lưu trữ nguyên bản của nền tảng:

  • iOS: NSUserDefaults
  • Android: SharedPreferences

Điều này có nghĩa là dữ liệu được lưu trữ một cách hiệu quả và an toàn theo cách mà hệ điều hành mong đợi.


Khi nào nên và không nên dùng SharedPreferences?

Nên dùng khi

  • Cần lưu trữ dữ liệu đơn giản, có kích thước nhỏ.
  • Dữ liệu dưới dạng cặp khóa-giá trị (String, int, bool, double, List<String>).
  • Dữ liệu không yêu cầu tính bảo mật cao (vì nó có thể dễ dàng được truy cập trên thiết bị).
  • Chỉ cần lưu trữ cấu hình hoặc tùy chọn của người dùng.

Không nên dùng khi:

  • Lưu trữ dữ liệu lớn hoặc phức tạp: Ví dụ: danh sách các đối tượng phức tạp, hình ảnh, video. Đối với trường hợp này, chúng ta nên xem xét cơ sở dữ liệu như SQLite, Hive, hoặc Isar.
  • Lưu trữ dữ liệu nhạy cảm, bảo mật cao: Mặc dù shared_preferences được lưu cục bộ, nó không được mã hóa mặc định và có thể bị truy cập bởi người dùng có kiến thức kỹ thuật. Đối với dữ liệu nhạy cảm (ví dụ: token bảo mật), chúng ta nên dùng các giải pháp lưu trữ an toàn hơn ví dụ như flutter_secure_storage. hoặc mã hóa thủ công trước khi lưu.
  • Lưu trữ dữ liệu cần tìm kiếm hoặc truy vấn phức tạp: shared_preferences không phải là một cơ sở dữ liệu; nó không hỗ trợ các truy vấn phức tạp.

Cài đặt

Để cài đặt shared_preferences chúng ta cần thêm thư viện vào trong file pubspec.yaml:

dependencies: shared_preferences: ^2.5.3

Sau khi thêm xong thì chúng ta chạy flutter pub get

Sử dụng shared_preferences

Trong file Dart mà chúng ta muốn sử dụng shared_preferences, hãy thêm dòng import:

import 'package:shared_preferences/shared_preferences.dart';

Lưu trữ dữ liệu (Ghi)

Để lưu trữ dữ liệu, chúng ta cần lấy một instance của SharedPreferences và sau đó sử dụng các phương thức set tương ứng. Các phương thức setBool, setInt, setDouble, setString, setStringList được sử dụng để lưu các loại dữ liệu khác nhau. Tất cả các phương thức này đều trả về một Future<bool>, cho biết thao tác có thành công hay không.

Future<void> saveData() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setBool('isDarkMode', true); await prefs.setInt('userAge', 30); await prefs.setString('userName', 'Nguyen Van A'); await prefs.setStringList('favoriteColors', ['red', 'green', 'blue']); print('Dữ liệu đã được lưu!');
}

Đọc dữ liệu

Các phương thức getBool, getInt, getDouble, getString, getStringList được sử dụng để đọc dữ liệu. Nếu khóa không tồn tại, chúng sẽ trả về null (hoặc giá trị mặc định của kiểu nếu không phải String hoặc List<String>).

Future<void> readData() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); final bool? isDarkMode = prefs.getBool('isDarkMode'); final int? userAge = prefs.getInt('userAge'); final String? userName = prefs.getString('userName'); final List<String>? favoriteColors = prefs.getStringList('favoriteColors'); print('isDarkMode: $isDarkMode'); // Output: true print('userAge: $userAge'); // Output: 30 print('userName: $userName'); // Output: Nguyen Van A print('favoriteColors: $favoriteColors'); // Output: [red, green, blue] // Lấy một khóa không tồn tại final String? nonExistentKey = prefs.getString('nonExistentKey'); print('nonExistentKey: $nonExistentKey'); // Output: null
}

Xóa dữ liệu

  • remove(String key): Xóa một cặp khóa-giá trị cụ thể.
  • clear(): Xóa tất cả dữ liệu đã lưu trữ bởi ứng dụng.
Future<void> removeData() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.remove('userAge'); // Xóa khóa 'userAge' print('Đã xóa userAge.'); // Để xóa tất cả dữ liệu: // await prefs.clear(); // print('Đã xóa tất cả dữ liệu.');
}

Ví dụ đầy đủ

Chúng ta cùng viết một app nhỏ: mỗi khi nhấn nút, số đếm sẽ tăng và vẫn được giữ nguyên khi mở lại ứng dụng.

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key});  Widget build(BuildContext context) { return const MaterialApp(home: CounterPage()); }
} class CounterPage extends StatefulWidget { const CounterPage({super.key});  State<CounterPage> createState() => _CounterPageState();
} class _CounterPageState extends State<CounterPage> { int _counter = 0;  void initState() { super.initState(); _loadCounter(); // Load khi mở app } Future<void> _loadCounter() async { final prefs = await SharedPreferences.getInstance(); setState(() { _counter = prefs.getInt('counter') ?? 0; }); } Future<void> _incrementCounter() async { final prefs = await SharedPreferences.getInstance(); setState(() { _counter++; }); await prefs.setInt('counter', _counter); // Lưu lại }  Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('SharedPreferences Demo')), body: Center(child: Text('Số lần bấm: $_counter', style: TextStyle(fontSize: 24))), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, child: const Icon(Icons.add), ), ); }
}

Kết luận

SharedPreferences là lựa chọn tuyệt vời cho những nhu cầu lưu trữ đơn giản, không nhạy cảm trong ứng dụng Flutter. Nó nhẹ, dễ dùng và cực kỳ tiện lợi cho việc ghi nhớ trạng thái ứng dụng, tuỳ chỉnh của người dùng, hay logic đơn giản.

Trong các bài viết tiếp theo, chúng ta sẽ cùng tìm hiểu về những giải pháp lưu trữ mạnh mẽ hơn, chẳng hạn như Hive, SQLite hoặc flutter_secure_storage.

Cảm ơn các bạn đã theo dõi. Chúc các bạn học tập hiệu quả. Nếu bài viết có sai sót hoặc chưa rõ ràng ở đâu xin các bạn hãy để lại một cmt để mình biết nhé.


Tham khảo

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 301

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

1 1 360

- vừa được xem lúc

Flutter Animation: Creating medium’s clap animation in flutte Part II

Trong phần 1 mình đã giới thiệu với các bạn cơ bản về Animation trong Flutter. Score Widget Size Animation.

0 0 72

- vừa được xem lúc

Flutter - GetX - Using GetConnect to handle API request (Part 4)

Giới thiệu. Xin chào các bạn, lại là mình với series về GetX và Flutter.

0 0 371

- vừa được xem lúc

StatefulWidget và StatelessWidget trong Flutter

I. Mở đầu. Khi các bạn build một ứng dụng với Flutter thì Widgets là thứ không thể thiếu đúng không ạ. Và 2 loại Widget không thể thiếu đó là StatefullWidget và StatelessWidget.

0 0 157

- vừa được xem lúc

Tìm hiểu về Riverpod - Provider nhưng không hắn :v

Trong Flutter có rất nhiều các quản lý state: Provider, Bloc, GetX, Redux,... khó mà nói cái nào tốt hơn cái nào. Tuy nhiên nếu bạn đã làm quen với Provider thì không ngại để tìm hiểu thêm về Riverpod. Một bản nâng cấp của Provider. Nếu bạn để ý thì cái tên "Riverpod" là các chữ cái của "Provider" đ

0 0 73