SQLite在安卓中的应用

打印 上一主题 下一主题

主题 1880|帖子 1880|积分 5640

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在 Android 应用程序中,SQLite 是默认的嵌入式数据库办理方案,Android 系统为开辟者提供了相应的 API 来管理 SQLite 数据库。通过利用 SQLiteOpenHelper 类和 SQLiteDatabase 类,开辟者可以方便地创建、查询、更新和删除数据库中的数据。
以下是关于如安在 Android 中利用 SQLite 的详细介绍和示例。

一、在 Android 中利用 SQLite 的步调

1. 创建 SQLiteOpenHelper 类

SQLiteOpenHelper 是一个辅助类,用于管理数据库的创建和版本管理。它提供了两个重要的方法:


  • onCreate(SQLiteDatabase db):当数据库第一次创建时调用。
  • onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):当数据库需要升级时调用。
示例:创建 SQLiteOpenHelper 子类
  1. public class MyDatabaseHelper extends SQLiteOpenHelper {
  2.     private static final String DATABASE_NAME = "MyDatabase.db";  // 数据库名称
  3.     private static final int DATABASE_VERSION = 1;                // 数据库版本
  4.     public MyDatabaseHelper(Context context) {
  5.         super(context, DATABASE_NAME, null, DATABASE_VERSION);
  6.     }
  7.     // 第一次创建数据库时调用
  8.     @Override
  9.     public void onCreate(SQLiteDatabase db) {
  10.         // 创建数据库中的表
  11.         String CREATE_TABLE = "CREATE TABLE users ("
  12.                 + "id INTEGER PRIMARY KEY AUTOINCREMENT,"
  13.                 + "name TEXT NOT NULL,"
  14.                 + "age INTEGER,"
  15.                 + "email TEXT);";
  16.         db.execSQL(CREATE_TABLE);
  17.     }
  18.     // 当数据库版本升级时调用
  19.     @Override
  20.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  21.         // 如果表已存在则删除,重新创建
  22.         db.execSQL("DROP TABLE IF EXISTS users");
  23.         onCreate(db);
  24.     }
  25. }
复制代码


  • DATABASE_NAME 界说了数据库的名称。
  • DATABASE_VERSION 是数据库的版本号,每当数据库布局发生变化时,需要升级版本号。
  • onCreate() 方法在数据库首次创建时调用,实验 SQL 语句来创建数据库中的表。
  • onUpgrade() 方法在数据库需要升级时调用,可以用于处理惩罚表布局的变更。
2. 打开数据库

利用 SQLiteOpenHelper 类时,可以通过调用 getWritableDatabase() 或 getReadableDatabase() 方法来打开数据库。前者允许实验写操作,而后者只允许实验读操作。
  1. MyDatabaseHelper dbHelper = new MyDatabaseHelper(context);
  2. SQLiteDatabase db = dbHelper.getWritableDatabase();
复制代码
3. 插入数据

利用 insert() 方法将数据插入到表中。
  1. // 创建一个 ContentValues 对象,用于存储键值对
  2. ContentValues values = new ContentValues();
  3. values.put("name", "Alice");
  4. values.put("age", 25);
  5. values.put("email", "alice@example.com");
  6. // 插入数据
  7. long newRowId = db.insert("users", null, values);
复制代码


  • ContentValues 类用于生存列名与列值的映射。
  • insert() 方法将数据插入到指定的表中,返回插入数据的行 ID。
4. 查询数据

利用 query() 方法从数据库中查询数据。该方法返回一个 Cursor 对象,用于遍历查询结果。
  1. // 定义要查询的列
  2. String[] projection = {
  3.     "id",
  4.     "name",
  5.     "age",
  6.     "email"
  7. };
  8. // 查询数据
  9. Cursor cursor = db.query(
  10.     "users",   // 表名
  11.     projection,   // 要返回的列
  12.     null,         // WHERE 子句
  13.     null,         // WHERE 子句的参数
  14.     null,         // GROUP BY 子句
  15.     null,         // HAVING 子句
  16.     null          // 排序方式
  17. );
  18. // 遍历查询结果
  19. while (cursor.moveToNext()) {
  20.     long userId = cursor.getLong(cursor.getColumnIndexOrThrow("id"));
  21.     String userName = cursor.getString(cursor.getColumnIndexOrThrow("name"));
  22.     int userAge = cursor.getInt(cursor.getColumnIndexOrThrow("age"));
  23.     String userEmail = cursor.getString(cursor.getColumnIndexOrThrow("email"));
  24. }
  25. // 关闭游标
  26. cursor.close();
复制代码


  • projection 界说了需要查询的列。
  • Cursor 对象用于从查询结果中提取数据,moveToNext() 方法用于遍历结果集。
5. 更新数据

利用 update() 方法更新表中的数据。
  1. // 创建 ContentValues 对象
  2. ContentValues values = new ContentValues();
  3. values.put("age", 26);
  4. // 更新记录
  5. String selection = "name = ?";
  6. String[] selectionArgs = { "Alice" };
  7. int count = db.update(
  8.     "users",    // 表名
  9.     values,     // 要更新的值
  10.     selection,  // WHERE 子句
  11.     selectionArgs  // WHERE 子句的参数
  12. );
复制代码


  • update() 方法根据指定的条件更新表中的纪录,返回受影响的行数。
6. 删除数据

利用 delete() 方法删除表中的数据。
  1. // 定义删除条件
  2. String selection = "name = ?";
  3. String[] selectionArgs = { "Alice" };
  4. // 删除记录
  5. int deletedRows = db.delete("users", selection, selectionArgs);
复制代码


  • delete() 方法根据指定的条件删除表中的纪录,返回删除的行数。

二、数据库操作的异步处理惩罚

在 Android 中,数据库操作通常需要在子线程中进行,以避免在主线程上实验耗时操作,防止壅闭 UI。
可以利用 AsyncTask、HandlerThread 或 Jetpack 提供的 Room 库来简化和管理异步的数据库操作。
利用 Room 作为 SQLite 的抽象层

Room 是 Android Jetpack 提供的一个长期性库,它简化了与 SQLite 的交互,并且支持异步查询。利用 Room 可以避免手动编写大量的 SQL 代码,并提供类型安全的 API。
Room 的基础组件:


  • 实体 (Entity):对应数据库中的表。
  • DAO (Data Access Object):界说数据操作方法。
  • 数据库 (Database):数据库持有者,管理实体和 DAO。
示例:利用 Room 管理数据库

  • 界说实体类:
  1. @Entity
  2. public class User {
  3.     @PrimaryKey(autoGenerate = true)
  4.     public int id;
  5.     public String name;
  6.     public int age;
  7.     public String email;
  8. }
复制代码

  • 界说 DAO 接口:
  1. @Dao
  2. public interface UserDao {
  3.     @Insert
  4.     void insertUser(User user);
  5.     @Query("SELECT * FROM User WHERE id = :id")
  6.     User getUserById(int id);
  7.     @Update
  8.     void updateUser(User user);
  9.     @Delete
  10.     void deleteUser(User user);
  11. }
复制代码

  • 创建数据库类:
  1. @Database(entities = {User.class}, version = 1)
  2. public abstract class AppDatabase extends RoomDatabase {
  3.     public abstract UserDao userDao();
  4. }
复制代码

  • 初始化 Room 数据库:
  1. AppDatabase db = Room.databaseBuilder(getApplicationContext(),
  2.         AppDatabase.class, "MyDatabase").build();
  3. // 在子线程中执行数据库操作
  4. new Thread(() -> {
  5.     User user = new User();
  6.     user.name = "Alice";
  7.     user.age = 25;
  8.     user.email = "alice@example.com";
  9.     db.userDao().insertUser(user);
  10. }).start();
复制代码

三、SQLite 数据库备份和恢复

由于 SQLite 数据存储在一个单一的文件中,因此备份和恢复操作非常简单。可以直接复制数据库文件来备份或恢复数据。
备份数据库文件:
  1. File dbFile = context.getDatabasePath("MyDatabase.db");
  2. File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");
  3. try (FileChannel src = new FileInputStream(dbFile).getChannel();
  4.      FileChannel dst = new FileOutputStream(backupFile).getChannel()) {
  5.     dst.transferFrom(src, 0, src.size());
  6. } catch (IOException e) {
  7.     e.printStackTrace();
  8. }
复制代码
恢复数据库文件:
  1. File dbFile = context.getDatabasePath("MyDatabase.db");
  2. File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");
  3. try (FileChannel src = new FileInputStream(backupFile).getChannel();
  4.      FileChannel dst = new FileOutputStream(dbFile).getChannel()) {
  5.     dst.transferFrom(src, 0, src.size());
  6. } catch (IOException e) {
  7.     e.printStackTrace();
  8. }
复制代码

四、SQLite 数据库的性能优化


  • 利用索引:为经常查询的列创建索引可以明显提升查询速度。
    1. CREATE INDEX idx_user_name ON users(name);
    复制代码
  • 事件处理惩罚:将多个操作放在一个事件中实验,可以减少磁盘 I/O,从而进步性能。
    1. BEGIN TRANSACTION;
    2. -- 执行多条 SQL 语句
    3. COMMIT;
    复制代码
  • 按需加载数据:在查询大量数据时,利用分页查询减少内存斲丧。
    1. SELECT * FROM users LIMIT 10 OFFSET 20;
    复制代码

通过上述步调,开辟者可以轻松在 Android 中集成并利用 SQLite 数据库。为了进一步深入理解,接下来将继承介绍 SQLite 在 Android 中的性能优化、常见的最佳实践,以及在不同场景下的高级用法。

五、SQLite 在 Android 中的性能优化

SQLite 数据库在 Android 应用中处理惩罚小规模数据时表现非常优秀,但当数据量增大时,大概会面临性能问题。以下是几种常见的性能优化方法:
1. 利用事件

将多条 SQL 操作放在一个事件中可以明显提升数据库操作的效率。SQLite 的每一条独立的插入或更新操作都会触发一次磁盘写操作,增加了 I/O 的开销。假如将多条插入或更新操作包裹在同一个事件中,则只会有一次磁盘写入,减少了 I/O 操作,极大进步了性能。
示例:利用事件插入多条纪录
  1. db.beginTransaction();
  2. try {
  3.     for (User user : userList) {
  4.         ContentValues values = new ContentValues();
  5.         values.put("name", user.getName());
  6.         values.put("age", user.getAge());
  7.         values.put("email", user.getEmail());
  8.         db.insert("users", null, values);
  9.     }
  10.     db.setTransactionSuccessful();  // 标记事务成功
  11. } finally {
  12.     db.endTransaction();  // 结束事务
  13. }
复制代码


  • db.beginTransaction() 开启事件。
  • db.setTransactionSuccessful() 在事件成功时调用。
  • db.endTransaction() 结束事件。
2. 利用索引 (Indexing)

为常用查询的列创建索引,可以加速查询速度。索引本质上是表中特定列的排序布局,它减少了查询时的扫描行数。
创建索引的示例:
  1. CREATE INDEX idx_user_name ON users(name);
复制代码
留意,固然索引可以加速查询速度,但也会增加插入和更新操作的开销,因此应根据需要平衡索引的利用。
3. 减少数据查询

在查询数据时,避免利用 SELECT * 来检索所有列,尽量只查询需要的列,减少不须要的数据传输。
示例:只查询需要的列
  1. String[] projection = {
  2.     "id",
  3.     "name"
  4. };
  5. Cursor cursor = db.query(
  6.     "users",
  7.     projection,
  8.     null,
  9.     null,
  10.     null,
  11.     null,
  12.     null
  13. );
复制代码
4. 利用批量操作

在处理惩罚大批量数据操作时,利用批量插入、更新或删除可以进步操作效率。批量操作可以通过事件和 SQLiteStatement 进步性能。
批量插入示例:
  1. SQLiteStatement stmt = db.compileStatement("INSERT INTO users (name, age, email) VALUES (?, ?, ?)");
  2. db.beginTransaction();
  3. try {
  4.     for (User user : userList) {
  5.         stmt.bindString(1, user.getName());
  6.         stmt.bindLong(2, user.getAge());
  7.         stmt.bindString(3, user.getEmail());
  8.         stmt.execute();
  9.         stmt.clearBindings();
  10.     }
  11.     db.setTransactionSuccessful();
  12. } finally {
  13.     db.endTransaction();
  14. }
复制代码
5. 利用 PRAGMA 进行性能调优

SQLite 提供了很多 PRAGMA 命令,允许开辟者动态设置数据库的举动,从而提升性能。例如:


  • PRAGMA synchronous = OFF;:关闭同步写入,提升写入速度(在数据同等性不是重要关注时利用)。
  • PRAGMA journal_mode = WAL;
    :将数据库设置为“写入时日志”模式,如许可以在高并发读写的场景下提升性能。
示例:设置 WAL 模式
  1. PRAGMA journal_mode = WAL;
复制代码
在 WAL 模式下,写操作不会直接覆盖原数据,而是纪录在日志中,并在空闲时间将日志内容合并回主数据库文件,从而进步并发读写的性能。

六、SQLite 的最佳实践

1. 善用 ContentValues 和 Cursor



  • 利用 ContentValues 来存储插入或更新的数据,不仅简化了代码,还进步了可读性。
  • 利用 Cursor 遍历查询结果时,始终在利用后关闭 Cursor,防止内存走漏。
关闭 Cursor 示例:
  1. Cursor cursor = db.query("users", null, null, null, null, null, null);
  2. try {
  3.     while (cursor.moveToNext()) {
  4.         // 获取数据
  5.     }
  6. } finally {
  7.     cursor.close();  // 确保 cursor 关闭
  8. }
复制代码
2. 利用 Room 框架

在复杂的 Android 应用程序中,直接利用 SQLite 大概会导致 SQL 语句冗长、难以维护。为了简化与 SQLite 的交互,推荐利用 Room 框架,它提供了类型安全的 API,并能与 LiveData 和 RxJava 轻松集成,实现异步查询操作。
3. 避免在主线程进行数据库操作

数据库操作大概会耗时较长,尤其是在处理惩罚大数据集或网络存储时。为了避免 UI 卡顿,务必在工作线程中实验数据库操作。可以利用 AsyncTask、ExecutorService 或 Room 提供的异步操作方法。
示例:利用 ExecutorService 进行异步操作
  1. ExecutorService executor = Executors.newSingleThreadExecutor();
  2. executor.execute(() -> {
  3.     // 在后台线程中执行数据库操作
  4.     db.userDao().insertUser(user);
  5. });
复制代码
4. 确保数据库版本管理

当数据库的布局发生变化时,需要通过增加数据库的版本号并在 onUpgrade() 中进行得当的迁移操作,以确保数据的完备性。
版本升级示例:
  1. @Override
  2. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  3.     if (oldVersion < 2) {
  4.         db.execSQL("ALTER TABLE users ADD COLUMN phone TEXT");
  5.     }
  6. }
复制代码
通过这种方式,可以安全地向数据库表中添加新字段,而不会粉碎现有数据。

七、SQLite 高级用法

1. 数据库加密

Android 系统默认的 SQLite 数据库是不加密的。假如需要对敏感数据进行加密,可以利用 SQLCipher 如许的第三方库。SQLCipher 是对 SQLite 的加强版,提供了对数据库文件的透明加密支持。
利用 SQLCipher 加密数据库:

  • 添加依赖:
  1. implementation 'net.zetetic:android-database-sqlcipher:4.5.0'
复制代码

  • 创建或打开加密数据库:
  1. SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(databaseFile, "your-password", null);
复制代码
通过加密,数据在数据库文件中存储时将是加密的,即使文件被拷贝,未经授权的用户也无法直接查看数据。
2. 数据库迁移

当应用程序的数据库架构需要更新时,必须处理惩罚好数据迁移。Room 框架提供了方便的迁移机制,可以资助开辟者在数据库版本升级时保持数据的完备性。
Room 迁移示例:
  1. Migration MIGRATION_1_2 = new Migration(1, 2) {
  2.     @Override
  3.     public void migrate(@NonNull SupportSQLiteDatabase database) {
  4.         database.execSQL("ALTER TABLE users ADD COLUMN phone TEXT");
  5.     }
  6. };
  7. Room.databaseBuilder(context, AppDatabase.class, "MyDatabase")
  8.     .addMigrations(MIGRATION_1_2)
  9.     .build();
复制代码
通过 Room 的迁移功能,数据库的版本升级变得更加安全和可控。
3. 数据库备份与恢复

SQLite 的备份和恢复操作可以通过文件操作来实现。开辟者可以直接复制 SQLite 数据库文件以创建备份,或者通过将文件移动到安全的存储位置来进行恢复。
示例:备份数据库文件到外部存储
  1. File dbFile = context.getDatabasePath("MyDatabase.db");
  2. File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");
  3. try (FileChannel src = new FileInputStream(dbFile).getChannel();
  4.      FileChannel dst = new FileOutputStream(backupFile).getChannel()) {
  5.     dst.transferFrom(src, 0, src.size());
  6. } catch (IOException e) {
  7.     e.printStackTrace();
  8. }
复制代码
示例:从备份文件恢复数据库
  1. File dbFile = context.getDatabasePath("MyDatabase.db");
  2. File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");
  3. try (FileChannel src = new FileInputStream(backupFile).getChannel();
  4.      FileChannel dst = new FileOutputStream(dbFile).getChannel()) {
  5.     dst.transferFrom(src, 0, src.size());
  6. } catch (IOException e) {
  7.     e.printStackTrace();
  8. }
复制代码

总结

SQLite 是一个轻量、可靠、简单易用的数据库办理方案,特别适合嵌入式系统和移动应用中的数据存储需求。通过 Android 提供的 API,开辟者可以轻松地实现数据长期化功能。在实际开辟中

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表