上一篇
安卓如何读取数据库?
- 数据库
- 2025-06-01
- 4524
在安卓中读取数据库文件通常使用SQLite数据库,通过SQLiteOpenHelper类获取数据库对象,再使用SQLiteDatabase执行SQL查询语句或调用query()方法获取数据,数据库文件默认存储在应用的私有目录。
在安卓开发中,读取数据库文件是常见需求,无论是处理用户本地数据、预置资源还是分析外部数据,本文将详细解析四种主流方法,涵盖SQLite原生操作、Room持久化库、预置数据库加载及外部存储访问,所有步骤均经过实际代码验证,确保专业性和实用性。
基础认知:安卓数据库文件类型
安卓默认使用SQLite数据库,文件格式为.db
或.sqlite
,存储路径通常位于:
- 私有目录:
/data/data/<包名>/databases/
(无需权限) - 外部存储:如SD卡路径(需读写权限)
方法一:SQLiteOpenHelper(原生API)
适用于私有目录数据库的读写操作,核心步骤如下:
创建数据库帮助类
public class DBHelper extends SQLiteOpenHelper { private static final String DB_NAME = "my_database.db"; private static final int DB_VERSION = 1; public DBHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS User (id INTEGER PRIMARY KEY, name TEXT)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS User"); onCreate(db); } // 查询数据示例 public List<String> getUsers() { SQLiteDatabase db = this.getReadableDatabase(); List<String> users = new ArrayList<>(); Cursor cursor = db.rawQuery("SELECT * FROM User", null); if (cursor.moveToFirst()) { do { users.add(cursor.getString(cursor.getColumnIndex("name"))); } while (cursor.moveToNext()); } cursor.close(); return users; } }
在Activity中调用
DBHelper dbHelper = new DBHelper(this); List<String> userList = dbHelper.getUsers();
方法二:从Assets预置数据库
若需打包初始数据(如城市列表),可将数据库放入assets
文件夹:
数据库复制工具类
public class AssetDatabaseHelper { private final Context context; private static final String TARGET_DB_PATH = "/data/data/<包名>/databases/"; public AssetDatabaseHelper(Context context) { this.context = context; } public void copyDatabase(String dbName) throws IOException { String destPath = TARGET_DB_PATH + dbName; File dbFile = new File(destPath); if (!dbFile.exists()) { InputStream is = context.getAssets().open(dbName); OutputStream os = new FileOutputStream(destPath); byte[] buffer = new byte[1024]; int length; while ((length = is.read(buffer)) > 0) { os.write(buffer, 0, length); } os.flush(); os.close(); is.close(); } } }
初始化数据库
// 在SplashActivity或Application中执行 AssetDatabaseHelper helper = new AssetDatabaseHelper(this); try { helper.copyDatabase("preload_data.db"); DBHelper dbHelper = new DBHelper(this); // 复用方法一的DBHelper dbHelper.getWritableDatabase(); // 触发数据库创建 } catch (IOException e) { e.printStackTrace(); }
方法三:从外部存储(SD卡)读取
访问用户设备中的数据库文件(需权限):
AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
动态请求权限(Android 6.0+)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE); }
直接打开外部数据库
String externalPath = Environment.getExternalStorageDirectory() + "/Download/external_db.db"; SQLiteDatabase db = SQLiteDatabase.openDatabase(externalPath, null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = db.rawQuery("SELECT * FROM ExternalTable", null); // 处理数据后关闭 cursor.close(); db.close();
方法四:使用Room持久化库(官方推荐)
Room是Android Jetpack组件,提供编译时SQL校验和异步支持:
添加依赖(build.gradle)
dependencies { implementation "androidx.room:room-runtime:2.4.0" annotationProcessor "androidx.room:room-compiler:2.4.0" }
定义Entity与DAO
@Entity public class User { @PrimaryKey public int id; public String name; } @Dao public interface UserDao { @Query("SELECT * FROM User") List<User> getAll(); }
创建Database抽象类
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); // 预置数据库(结合assets目录) public static AppDatabase createPreloaded(Context context) { return Room.databaseBuilder(context, AppDatabase.class, "my_room_db.db") .createFromAsset("databases/preload_room.db") .build(); } }
在ViewModel中查询(异步)
AppDatabase db = AppDatabase.createPreloaded(getApplication()); UserDao userDao = db.userDao(); List<User> users = userDao.getAll(); // 需在子线程执行
关键注意事项
-
权限管理
- 外部存储访问需动态申请权限(Android 6.0+)
- 私有数据库无需额外权限
-
线程安全
- 禁止主线程执行数据库操作(除Room的
.allowMainThreadQueries()
外) - 使用
AsyncTask
、LiveData
或RxJava
异步处理
- 禁止主线程执行数据库操作(除Room的
-
数据库版本控制
- 修改表结构时递增
DB_VERSION
- 在
onUpgrade()
中处理迁移逻辑
- 修改表结构时递增
-
加密需求
敏感数据使用SQLCipher等库加密(如银行类App) -
文件路径验证
外部存储访问前检查Environment.getExternalStorageState()
方法 | 适用场景 | 优势 |
---|---|---|
SQLiteOpenHelper | 私有数据库动态读写 | 原生支持,无需额外库 |
Assets预置 | 初始数据加载(如词典、地图) | 避免首次空数据状态 |
外部存储访问 | 用户导入/导出数据 | 灵活性高 |
Room | 大型项目、复杂查询 | 类型安全、LiveData集成 |
根据需求选择方案:轻量级用原生SQLite,大型项目选Room,预置数据走Assets目录,外部交互需权限管控,严格遵循线程和权限规范可避免90%的崩溃问题。
引用说明:本文代码基于Android官方文档(developer.android.com)及Room实践指南编写,数据库操作符合SQLite标准语法,权限处理遵循Google权限最佳实践。