在 Android 开发里,数据存储是非常重要的一环。今天咱们就来聊聊 Android 里两种常见的数据存储方案:SharedPreferences 和 Room 数据库,并且通过实战来对比它们。

一、SharedPreferences 是什么

SharedPreferences 就像是一个小仓库,专门用来存放一些简单的数据,比如用户的偏好设置、一些临时的状态信息啥的。它操作起来特别简单,就像在一个小本本上记录东西一样。

示例(Java 技术栈)

// 获取 SharedPreferences 实例,这里使用 getSharedPreferences 方法,第一个参数是文件名,第二个参数是访问模式
SharedPreferences sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE);
// 获取 Editor 对象,用于对 SharedPreferences 进行写入操作
SharedPreferences.Editor editor = sharedPreferences.edit();
// 存入一个字符串数据,键为 "username",值为 "John"
editor.putString("username", "John");
// 存入一个整数数据,键为 "age",值为 25
editor.putInt("age", 25);
// 提交写入操作
editor.apply();

// 读取数据
// 从 SharedPreferences 中获取字符串数据,键为 "username",如果没有找到则返回默认值 "Unknown"
String username = sharedPreferences.getString("username", "Unknown");
// 从 SharedPreferences 中获取整数数据,键为 "age",如果没有找到则返回默认值 0
int age = sharedPreferences.getInt("age", 0);

应用场景

  • 用户偏好设置:比如用户选择的主题、字体大小等。
  • 临时状态记录:像是否第一次打开应用这种简单的状态。

技术优缺点

  • 优点:操作简单,代码量少,对于简单数据的存储和读取非常方便。
  • 缺点:只能存储简单的数据类型,比如字符串、整数、布尔值等,而且不适合存储大量数据。

注意事项

  • 不要在 SharedPreferences 里存储大量数据,不然会影响性能。
  • 不同的应用组件(Activity、Service 等)可以共享同一个 SharedPreferences 文件,但要注意数据的一致性。

二、Room 数据库是什么

Room 数据库就像是一个大型的图书馆,它可以存储大量的结构化数据,并且提供了强大的查询功能。它是基于 SQLite 数据库封装的,使用起来更加方便。

示例(Java 技术栈)

首先,我们需要定义一个实体类,这个类就像是图书馆里的一本书,里面有各种信息。

// 使用 @Entity 注解将这个类标记为数据库中的一个表
@Entity(tableName = "users")
public class User {
    // 使用 @PrimaryKey 注解将 id 字段标记为主键
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String name;
    private int age;

    // 构造函数
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter 和 Setter 方法
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

然后,我们需要定义一个 DAO(数据访问对象)接口,这个接口就像是图书馆的管理员,负责对数据进行增删改查操作。

// 使用 @Dao 注解将这个接口标记为数据访问对象
@Dao
public interface UserDao {
    // 使用 @Insert 注解表示这是一个插入操作
    @Insert
    void insert(User user);

    // 使用 @Query 注解表示这是一个查询操作,查询所有用户
    @Query("SELECT * FROM users")
    List<User> getAllUsers();

    // 使用 @Update 注解表示这是一个更新操作
    @Update
    void update(User user);

    // 使用 @Delete 注解表示这是一个删除操作
    @Delete
    void delete(User user);
}

最后,我们需要定义一个 RoomDatabase 类,这个类就像是图书馆的馆长,负责管理整个数据库。

// 使用 @Database 注解将这个类标记为数据库,entities 表示数据库中的表,version 表示数据库的版本
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

在 Activity 中使用 Room 数据库:

// 获取 Room 数据库实例,这里使用 Room.databaseBuilder 方法,第一个参数是上下文,第二个参数是数据库类,第三个参数是数据库名
AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "users-database").build();
// 获取 UserDao 实例
UserDao userDao = db.userDao();

// 插入数据
User user = new User("Alice", 30);
userDao.insert(user);

// 查询数据
List<User> users = userDao.getAllUsers();
for (User u : users) {
    Log.d("RoomExample", "Name: " + u.getName() + ", Age: " + u.getAge());
}

应用场景

  • 存储大量的结构化数据,比如联系人信息、笔记等。
  • 需要进行复杂查询的场景,比如按条件筛选数据。

技术优缺点

  • 优点:可以存储大量数据,支持复杂的查询操作,代码结构清晰,便于维护。
  • 缺点:相比 SharedPreferences,代码量要多一些,学习成本相对较高。

注意事项

  • 数据库版本更新时,要注意数据迁移,避免数据丢失。
  • 不要在主线程中进行数据库操作,不然会导致界面卡顿。

三、SharedPreferences 与 Room 数据库的对比

数据类型

  • SharedPreferences 只能存储简单的数据类型,如字符串、整数、布尔值等。
  • Room 数据库可以存储复杂的对象,只要将其定义为实体类即可。

数据量

  • SharedPreferences 不适合存储大量数据,因为它的性能会随着数据量的增加而下降。
  • Room 数据库可以存储大量数据,并且有较好的性能。

操作复杂度

  • SharedPreferences 操作简单,代码量少。
  • Room 数据库操作相对复杂,需要定义实体类、DAO 接口和数据库类。

查询功能

  • SharedPreferences 没有查询功能,只能根据键来获取值。
  • Room 数据库提供了强大的查询功能,可以进行复杂的条件查询。

四、实战应用

假设我们要开发一个简单的备忘录应用,需要存储备忘录的标题和内容。

使用 SharedPreferences

// 获取 SharedPreferences 实例
SharedPreferences sharedPreferences = getSharedPreferences("memoPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
// 存入备忘录标题和内容
editor.putString("title", "My Memo");
editor.putString("content", "This is a memo.");
editor.apply();

// 读取备忘录标题和内容
String title = sharedPreferences.getString("title", "");
String content = sharedPreferences.getString("content", "");

使用 Room 数据库

首先定义实体类:

@Entity(tableName = "memos")
public class Memo {
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String title;
    private String content;

    public Memo(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

然后定义 DAO 接口:

@Dao
public interface MemoDao {
    @Insert
    void insert(Memo memo);

    @Query("SELECT * FROM memos")
    List<Memo> getAllMemos();
}

最后在 Activity 中使用:

AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "memos-database").build();
MemoDao memoDao = db.memoDao();

// 插入备忘录
Memo memo = new Memo("My Memo", "This is a memo.");
memoDao.insert(memo);

// 查询备忘录
List<Memo> memos = memoDao.getAllMemos();
for (Memo m : memos) {
    Log.d("MemoExample", "Title: " + m.getTitle() + ", Content: " + m.getContent());
}

五、文章总结

SharedPreferences 和 Room 数据库在 Android 开发中都有各自的应用场景。SharedPreferences 适合存储简单的、少量的数据,操作简单方便;而 Room 数据库适合存储大量的、结构化的数据,并且提供了强大的查询功能。在实际开发中,我们要根据具体的需求来选择合适的数据存储方案。如果只是存储一些简单的用户偏好设置,那么 SharedPreferences 是一个不错的选择;如果需要存储大量的结构化数据,并且需要进行复杂的查询操作,那么 Room 数据库会更合适。