SharedPreferences chỉ hỗ trợ các kiểu dữ liệu cơ bản (String, int, boolean, float, long, Set<String>). Để lưu ArrayList<Object> hoặc List<String>, cần serialize thành JSON (Gson) hoặc dùng Set<String> (chỉ cho String).
Cách 1: Dùng Gson (Khuyến nghị - hỗ trợ object phức tạp)
Dependency
dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
}
Model Class
public class User {
private String name;
private String email;
private int age;
// Getters, setters, constructors...
}
Helper Class
import android.content.Context;
import android.content.SharedPreferences;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class PrefsManager {
private static final String PREFS_NAME = "app_prefs";
private static final String KEY_USER_LIST = "user_list";
private final SharedPreferences prefs;
private final Gson gson = new Gson();
private final Type userListType = new TypeToken>(){}.getType();
public PrefsManager(Context context) {
prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
}
// Lưu List
public void saveUserList(List users) {
String json = gson.toJson(users);
prefs.edit().putString(KEY_USER_LIST, json).apply();
}
// Lấy List
public List getUserList() {
String json = prefs.getString(KEY_USER_LIST, null);
if (json == null) return new ArrayList<>();
List list = gson.fromJson(json, userListType);
return list != null ? list : new ArrayList<>();
}
// Thêm user
public void addUser(User user) {
List list = getUserList();
list.add(user);
saveUserList(list);
}
// Xóa user
public void removeUser(User user) {
List list = getUserList();
list.remove(user);
saveUserList(list);
}
// Clear all
public void clearUserList() {
prefs.edit().remove(KEY_USER_LIST).apply();
}
}
Sử dụng trong Activity
public class MainActivity extends AppCompatActivity {
private PrefsManager prefsManager;
private EditText etName, etEmail, etAge;
private TextView tvResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
prefsManager = new PrefsManager(this);
etName = findViewById(R.id.etName);
etEmail = findViewById(R.id.etEmail);
etAge = findViewById(R.id.etAge);
tvResult = findViewById(R.id.tvResult);
findViewById(R.id.btnSave).setOnClickListener(v -> saveUser());
findViewById(R.id.btnLoad).setOnClickListener(v -> loadUsers());
findViewById(R.id.btnClear).setOnClickListener(v -> clearUsers());
}
private void saveUser() {
String name = etName.getText().toString().trim();
String email = etEmail.getText().toString().trim();
String ageStr = etAge.getText().toString().trim();
if (name.isEmpty() || email.isEmpty() || ageStr.isEmpty()) {
Toast.makeText(this, "Nhập đầy đủ thông tin", Toast.LENGTH_SHORT).show();
return;
}
User user = new User(name, email, Integer.parseInt(ageStr));
prefsManager.addUser(user);
Toast.makeText(this, "Đã lưu: " + name, Toast.LENGTH_SHORT).show();
clearInputs();
}
private void loadUsers() {
List users = prefsManager.getUserList();
if (users.isEmpty()) {
tvResult.setText("Chưa có dữ liệu");
return;
}
StringBuilder sb = new StringBuilder("Danh sách user:\n");
for (User u : users) {
sb.append("- ").append(u.getName()).append(" (").append(u.getEmail()).append(", ").append(u.getAge()).append(")\n");
}
tvResult.setText(sb.toString());
}
private void clearUsers() {
prefsManager.clearUserList();
tvResult.setText("Đã xóa toàn bộ");
}
}
Cách 2: Dùng Set<String> (Chỉ cho List<String> đơn giản)
Không cần Gson, nhưng chỉ lưu được String, không giữ thứ tự (HashSet), không hỗ trợ object.
// Lưu SetstringSet = new HashSet<>(myStringList); prefs.edit().putStringSet("key_string_set", stringSet).apply(); // Lấy Set savedSet = prefs.getStringSet("key_string_set", new HashSet<>()); List list = new ArrayList<>(savedSet); // Thứ tự có thể thay đổi
Cách 3: DataStore (Modern replacement - Jetpack)
SharedPreferences đã cũ. DataStore (Preferences DataStore / Proto DataStore) là thay thế hiện đại:
// build.gradle implementation "androidx.datastore:datastore-preferences:1.0.0" // Sử dụng (coroutines) val Context.dataStore: DataStoreby preferencesDataStore("settings") // Lưu suspend fun saveList(list: List ) { dataStore.edit { preferences -> preferences[STRING_SET_KEY] = list.toSet() } } // Đọc (Flow) val listFlow: Flow > = dataStore.data .map { prefs -> prefs[STRING_SET_KEY]?.toList() ?: emptyList() } .catch { emit(emptyList()) }
Layout activity_main.xml (Mẫu)
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<EditText android:id="@+id/etName" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Tên" />
<EditText android:id="@+id/etEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Email" android:inputType="textEmailAddress" />
<EditText android:id="@+id/etAge" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Tuổi" android:inputType="number" />
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="16dp">
<Button android:id="@+id/btnSave" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Lưu" />
<Button android:id="@+id/btnLoad" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Đọc" />
<Button android:id="@+id/btnClear" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Xóa" />
</LinearLayout>
<TextView android:id="@+id/tvResult" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="Kết quả..." />
</LinearLayout>
Chạy ứng dụng
Nhập tên, email, tuổi → Nhấn "Lưu" → Nhấn "Đọc" hiển thị danh sách. "Xóa" clear toàn bộ SharedPreferences.
Lưu ý quan trọng
- apply() async (không block UI), commit() sync (tránh dùng trên main thread)
- SharedPreferences không phù hợp cho dữ liệu lớn (> 몇 MB) hoặc truy xuất phức tạp → Dùng Room Database
- Gson TypeToken cần khai báo đúng generic type để deserialize chính xác
- DataStore là tương lai - cân nhắc migrate cho project mới