Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Lưu ArrayList vào SharedPreferences Android

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
Set stringSet = 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: DataStore by 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