上一篇
安卓开发怎么查询数据
- 行业动态
- 2025-04-22
- 6
本地数据库查询(SQLite/Room)
SQLite 原生查询
- 适用场景:直接操作数据库,适合简单需求或第三方库不支持的情况。
- 示例代码:
SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT FROM user WHERE age > ?", new String[]{"20"}); if (cursor.moveToFirst()) { do { String name = cursor.getString(cursor.getColumnIndex("name")); // 处理数据 } while (cursor.moveToNext()); } cursor.close();
- 缺点:需手动管理线程、SQL 注入风险、无编译时校验。
Room 持久化库
- 优势:编译时校验 SQL、支持 LiveData 自动更新、简化线程处理。
- 查询方式:
- 普通查询:
@Dao public interface UserDao { @Query("SELECT FROM user WHERE age > :age") List<User> getUsersByAge(int age); }
- 流式查询(支持实时更新):
@Query("SELECT FROM user WHERE age > :age") LiveData<List<User>> getUsersByAgeLiveData(int age);
- 普通查询:
- 表格对比:
| 特性 | SQLite 原生 | Room |
|———————|————————|————————–|
| 编译时校验 | | |
| 线程管理 | 需手动处理 | 自动处理(异步查询) |
| 数据变更监听 | 需手动实现 | 支持 LiveData/Flow |
| 防止 SQL 注入 | 需手动处理 | 编译时校验参数 |
网络数据查询(Retrofit/OkHttp)
Retrofit + Callback
适用场景:RESTful API 请求,支持多种数据格式(JSON/XML)。
-
示例代码:
public interface ApiService { @GET("users") Call<List<User>> getUsers(@Query("age") int age); } Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService apiService = retrofit.create(ApiService.class); apiService.getUsers(20).enqueue(new Callback<>() { @Override public void onResponse(Call<List<User>> call, Response<List<User>> response) { // 处理成功结果 } @Override public void onFailure(Call<List<User>> call, Throwable t) { // 处理失败 } });
缺点:回调嵌套导致代码复杂(可结合 RxJava 或协程优化)。
Retrofit + 协程(Kotlin)
优势:避免回调地狱,代码更简洁。
示例代码:
interface ApiService { @GET("users") suspend fun getUsers(@Query("age") age: Int): List<User> } val retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build() val apiService = retrofit.create(ApiService::class.java) GlobalScope.launch { try { val users = apiService.getUsers(20) // 更新 UI } catch (e: Exception) { // 处理异常 } }
表格对比:
| 特性 | Callback 模式 | 协程模式 |
|———————|—————————-|————————–|
| 代码简洁度 | 低(嵌套回调) | 高(顺序执行) |
| 异常处理 | 需手动 try/catch | 可直接抛出/捕获 |
| 线程管理 | 需手动切换 | 自动继承协程上下文 |
其他数据查询方式
ContentProvider(系统级数据)
- 适用场景:读取系统数据(如联系人、文件)或跨应用共享数据。
- 示例代码:
Uri uri = ContactsContract.Contacts.CONTENT_URI; Cursor cursor = context.getContentResolver().query( uri, null, // 所有列 "age > ?", new String[]{"20"}, null ); // 解析 cursor...
- 限制:需处理权限(如
READ_CONTACTS
),API 复杂度较高。
Realm 数据库
- 特点:支持离线、实时更新,适合高频读写场景。
- 查询示例:
RealmResults<User> results = realm.where(User.class) .greaterThan("age", 20) .findAll();
- 注意:需学习特定语法,社区支持不如 Room。
常见问题与解答
问题1:如何优化数据库查询性能?
- 解答:
- 索引优化:为频繁查询的字段(如
age
)添加索引。 - 分页查询:使用
LIMIT
和OFFSET
(SQLite)或PagingSource
(Room)。 - 缓存机制:结合
LiveData
或内存缓存减少重复查询。 - 异步处理:避免在主线程执行耗时操作。
- 索引优化:为频繁查询的字段(如
问题2:网络请求如何实现分页加载?
- 解答:
- Retrofit + 协程:
interface ApiService { @GET("users") suspend fun getUsers(@Query("page") page: Int, @Query("limit") limit: Int): List<User> } // 调用时动态传递 page 参数
- Paging3 库:
val pager = Pager(config = PagingConfig(pageSize = 20)) { apiService.getUsers(it, 20) // it 为当前页码 } // 通过 flow 获取分页数据
- Retrofit + 协程:
- 本地查询:优先使用 Room(安全性、便捷性),复杂场景考虑 Realm。
- 网络查询:推荐 Retrofit + 协程(代码简洁),或结合 RxJava(功能丰富)。
- 系统数据:通过 ContentProvider 读取,注意权限管理