在 Android 开发中,SQLite是一个轻量级的关系型数据库管理系统,经常用于存储和管理应用程序的数据。如果你刚刚学习Android数据库的使用,你一定要学习SQLite的使用。以下是一个简单的示例,展示了如何在 Android 应用中创建 SQLite 数据库、创建表、插入数据以及查询数据。
public class DBHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "mydatabase";
private static final int DATABASE_VERSION = 1;
// 构造方法
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 创建表
String createTableQuery = "CREATE TABLE mytable ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "name TEXT,"
+ "age INTEGER)";
db.execSQL(createTableQuery);
}
}
public class MainActivity extends AppCompatActivity {
private DBHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new DBHelper(this);
// 插入数据示例
insertData("Alice", 25);
insertData("Bob", 30);
// 查询数据示例
String data = queryData();
Toast.makeText(this, "Data: " + data, Toast.LENGTH_SHORT).show();
}
private void insertData(String name, int age) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", name);
values.put("age", age);
db.insert("mytable", null, values);
db.close();
}
private String queryData() {
SQLiteDatabase db = dbHelper.getReadableDatabase();
String[] projection = {"name", "age"};
Cursor cursor = db.query("mytable", projection, null, null, null, null, null);
StringBuilder data = new StringBuilder();
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
int age = cursor.getInt(cursor.getColumnIndexOrThrow("age"));
data.append("Name: ").append(name).append(", Age: ").append(age).append("\n");
}
cursor.close();
db.close();
return data.toString();
}
}
其中涉及的知识点简要如下:
如果你没有使用任何 SQLite 数据库查看工具或者终端命令行,在 Android 应用程序中,SQLite 数据库通常存储在应用的私有目录中。这个目录的路径包含你的应用程序的包名,具体位置如下:
如果你在模拟器上运行应用程序,你可以使用 Android Studio 的 Device File Explorer来查看应用的数据目录。
数据库文件通常位于 /data/data/your.app.package/databases/ 目录下,其中 your.app.package 是你的应用程序的包名。
(嘿嘿嘿,不会以为自己命名,熬到交付就老板不敢裁掉你了吧,毕竟如果交给别人,别人看不懂,嘘~别瞎试)
除了 Helper 和 Contract,在特定的框架或架构设计下,当然还可能会使用其他后缀或命名约定,例如:
呜呜呜,终于到文章的重点了。既然我们简单的使用SQLite已经无法满足你求知的心,那我们来进一步来一点高级货,香得勒
Room 是 Android 官方提供的一个持久化库,是一个用于在 SQLite 数据库上进行抽象化和简化Android应用中数据库操作的一个ORM框架。它通过将数据库表映射为Java或Kotlin中的实体类(Entity),以及提供数据访问对象(DAO)来简化数据库操作。ROOM框架支持编译时SQL验证,减少了运行时错误,并且简化了数据库迁移的过程。它允许开发者使用更高级别的抽象概念来操作数据库,从而简化了数据存储和访问的过程。
实体类用于表示数据库中的表。每个实体类都需要用@Entity注解标记,以指明它是一个数据库表。
实体类中的字段默认会被映射为表中的列,除非使用@Ignore注解来忽略某个字段。
每个实体类都必须至少定义一个主键字段,用于唯一标识表中的每一行。主键字段可以使用@PrimaryKey注解来标记。
@Entity(tableName = "users")
public class User {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
DAO是ROOM框架中的核心组件,它定义了与数据库交互的方法,如增删改查(CRUD)操作。
DAO通常是一个接口,里面包含了多个使用@Insert、@Delete、@Update、@Query等注解标记的方法。
ROOM框架在编译时会为这些DAO接口自动生成实现类,使得开发者无需编写繁琐的SQL语句。
@Dao
public interface UserDao {
@Query("SELECT * FROM users")
List<User> getAllUsers();
@Insert
void insert(User user);
@Delete
void delete(User user);
@Update
void update(User user);
}
数据库类用于定义数据库的配置,并作为应用与数据库交互的主要入口点。
数据库类必须是一个继承自RoomDatabase的抽象类,并使用@Database注解来标记。
在@Database注解中,需要指定数据库中包含的实体类(通过entities属性),以及数据库的版本号(通过version属性)。
数据库类中还需要定义一些抽象方法,这些方法返回DAO接口的实例,以便在应用中使用这些DAO来与数据库交互。
@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class MyAppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
除此之外,你还可以设计这些:
仓库类(推荐使用哦)
虽然ROOM框架本身不直接要求仓库类,但使用仓库模式是一种将数据访问逻辑与应用业务逻辑分离的好方法。仓库类通常封装了对DAO的调用,并可能还包含缓存逻辑或数据转换逻辑。
示例:UserRepository.java,封装了与User相关的所有数据库操作,并提供更高级别的数据访问接口,让你的代码更加专业。
ViewModel和LiveData/Flow(推荐推荐,与UI交互)
虽然它们不是ROOM框架直接的一部分,但ViewModel和LiveData/Flow是Android Jetpack组件,常与ROOM一起使用来实现响应式UI更新。ViewModel负责准备和管理UI相关的数据,而LiveData或Flow则用于在数据发生变化时通知UI进行更新。
示例:UserViewModel.java,包含LiveData或Flow对象,这些对象在User数据发生变化时更新UI。
天哪,这个真的很管用,尤其如果你要使用MVVM和MVP整体架构的时候。
implementation "androidx.room:room-runtime:2.5.0"
annotationProcessor "androidx.room:room-compiler:2.5.0"
编译时检查:Room 在编译时会检查 SQL 查询的语法和类型,这可以帮助开发者在编译期间发现潜在的错误。(这其实在某一点上要求你需要提前设计好数据库表,不然作为一个一个小白,你编写完运行后,再来修改你的表,你会看到很多报错,不致命,但心梗,哈哈哈。)
简化数据库操作:通过使用注解和少量的代码,开发者可以轻松地执行数据库操作,而不必编写大量的样板代码。(除去一些ROOM框架无法支持的数据库操作语言,你可能在你的Android studio里看不到SQLite的代码,它自动帮你补充完整,多香啊)
LiveData 支持:Room 可以与 Android 架构组件中的 LiveData 结合使用,使得数据库中数据的变化可以自动通知 UI 层,从而简化了数据的观察和更新流程。(这个很重要哦,需要了解)
轻量级:Room 库本身很小,并且不会增加 APK 的大小太多,适合用于移动设备。(对于一些小应用真的再合适不过啦)
ROOM框架支持数据库迁移,当数据库结构发生变化时(如添加新字段、修改表名等),可以通过编写迁移类并指定迁移的起始版本号和目标版本号来实现平滑迁移。
ROOM框架支持在编译时验证SQL查询语句,减少运行时错误。此外,还可以通过在实体类中使用@Index注解为字段添加索引,以提高查询效率。
验证SQL查询语句
@Dao
public interface UserDao {
@Query("SELECT * FROM users WHERE name = :name") //这儿
User findByName(String name);
}
为字段添加索引
@Entity(indices = {@Index(value = {"firstName", "lastName"}, unique = true)})
public class User {
@PrimaryKey
public int id;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
// 其他字段和方法
}
ROOM框架与Kotlin协程(Coroutine)无缝集成,可以在协程中执行数据库操作,避免在主线程中进行耗时操作导致的界面卡顿问题。
ROOM提供了对Kotlin协程的扩展支持,使得数据库操作可以更加简洁地以异步方式执行。开发者可以在DAO接口的方法中使用suspend修饰符,并在调用这些方法时使用协程上下文来执行它们。
ROOM还提供了与Kotlin Flow的集成,允许开发者以响应式编程的方式处理数据库查询结果。通过使用Flow,开发者可以轻松地监听数据库查询结果的变化,并在结果更新时自动更新UI。
好了,溜了,溜了