[Android] Tìm hiểu về Shared Preferences trong Android
Shared Preferences là nơi bạn có thể lưu trữ các thông tin dưới dạng key-value được xây dựng sẵn trong hệ điều hành Android. Cùng tìm hiểu Shared Preferences hoạt động như thế nào và cách sử dụng nó trong bài viết này nhé!
1. Cấu trúc bên trong của Shared Preferences
Bạn có thể hình dung cấu trúc bên trong Shared Preferences là một bộ nhớ in-memory (RAM) đặt trên một bộ nhớ disk-storage (External Storage). Mọi thao tác đều đi qua bộ nhớ in-memory đầu tiên sau đó mới đến disk-storage trong trường hợp cần thiết.
- Bộ nhớ In-Memory về bản chất là một Hash-Map, điều đó cho phép các thao tác đều có độ phức tạp là O(1) khi chạy.
val map = HashMap<String, Any>()
- Disk Storage thực chất là một file xml được cấu trúc như sau:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="KEY">value</string>
</map>
2. Sử dụng Shared Preferences
2.1. Lấy instance của Shared Pref
Sử dụng hàm getSharedPreferences(Name, Mode) để lấy 1 instance của Shared Preferences với Name là tên của Shared Preferences
SharedPreference mode:
- MODE_PRIVATE: chỉ ứng dụng có thể truy nhập vào
- MODE_WORLD_READABLE: các ứng dụng khác có thể đọc được nội dung nhưng không thể sửa hoặc thêm
- MODE_WORLD_WRITABLE: Ứng dụng khác có thể đọc/ghi nội dung
- MODE_MULTI_PROCESS: Nhiều process có thể cùng chỉnh sửa SharedPreference
Đoạn code dưới đây sẽ lấy một instance của shared preferences với tên "PREF". Instance này có thể được sử dụng trong phạm vi toàn bộ ứng dụng bất cứ đâu nó được lấy về.
val pref = getSharedPreferences("PREF", MODE_PRIVATE)
Mỗi một shared preferences sẽ có instance riêng dựa trên tên của preference.
val pref2 = getSharedPreferences("PREF2", MODE_PRIVATE)
pref và pref2 là 2 instance khác nhau bởi vì chúng được lấy từ 2 Shared Preferences khác tên.
Không quan trọng trong context nào (Activity, Fragment, Application, ...) mà nó được gọi, nó luôn luôn trả về instance giống nhau khi bạn gọi method trên với tên giống nhau. Điều này đảm bảo rằng bạn luôn luôn nhận được dữ liệu mới nhất được lưu.
pref2 và pref3 sử dụng cùng một tên Shared Preferences trong lệnh gọi nên chúng là cùng 1 instance
2.2. Lấy dữ liệu
Tất cả các thao tác được đi qua bộ nhớ In-Memory, điều đó có nghĩa là ngay lập tức và tránh được các thao tác I/O. Bởi vì tất cả các thao tác đi qua bộ nhớ in-memory nên nó đảm bảo rằng giá trị trả về sẽ là giá trị mới nhất.
Các hàm lấy dữ liệu:
- getBoolean()
- getInt()
- getLong()
- getFloat()
- getString()
Ví dụ:
val value = pref.getString(key, null)
Chú ý: Nếu lần đầu dữ liệu được tải lên, nó sẽ đợi cho đến khi dữ liệu được loaded vào bộ nhớ in-memory từ disk storage.
2.3. Lưu dữ liệu
Các hàm lưu dữ liệu:
- putBoolean()
- putInt()
- putLong()
- putFloat()
- putString()
Lưu dữ liệu thông qua commit()
Lưu dữ liệu vào in-memory trước sau đó thực hiện ghi vào disk một cách đồng bộ. Bởi vì có sự tham gia của thao tác I/O, main thread sẽ bị blocked cho đến khi data được ghi hết vào disk storage. Đây là một thao tác kém hiệu quả so với apply()
Bởi vì thao tác ghi dữ liệu lên disk storage là đồng bộ cho nên trạng thái trả về sẽ là một biến boolean. Do đó bạn có thể xác nhận rằng liệu thao tác mà bạn thực hiện có thành công hay không bằng cách kiểm tra kết quả trả về.
val result = pref.edit().putString(key, "value").commit()
Lưu giá trị thông qua apply()
Lưu giá trị vào in-memory trước sau đó ghi dữ liệu một cách bất đồng bộ vào disk-storage. Main thread sẽ không bị blocked và không phải đợi thao tác trên disk nữa. Tuy thao tác ghi lên disk storage là asynchronous nhưng bất kỳ thao tác read ngay sau lời gọi apply() sẽ đều trả về kết quả là mới nhất bởi vì thao tác read(get) sẽ được thực thi thông qua in-memory.
Bởi vì thao tác ghi dữ liệu lên disk-storage là asynchronous, sẽ không có giá trị nào được trả về. Do đó bạn không thể xác nhận được là liệu thao tác bạn thực thi có thành công hay không,
Hãy sử dụng apply trừ khi bạn bạn cần xác nhận kết quả của thao tác bạn thực hiện.
pref.edit().putString(key, "value").apply()
2.4. Các thao tác khác
Ngoại trừ việc put và get, shared preferences còn cung cấp các thao tác sau:
- Kiểm tra xem một key có tồn tại hay không
- Lắng nghe việc thay đổi của shared preferences thông qua listener
- Đọc toàn bộ các entries thành map
- Xóa bỏ một entry
- Xóa bỏ toàn bộ các entries (Clear all)
Bonus
Shared preferences phạm vi ứng dụng được lưu tại đường dẫn
data/data/<YOUR_APP_ID>/shared_prefs/<SHARED_PREF_NAME>.xml
Bạn có thể lấy nó ra và mở ra xem dữ liệu bên trong.
Hi vọng qua bài viết này các bạn đã hiểu được Shared Preferences hoạt động như thế nào, sử dụng ra làm sao và có thể áp dụng vào các dự án sau này.
Cảm ơn các bạn đã đọc bài viết.
Chào thân ái và quyết thắng!
Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!