上一篇
安卓开发断网时如何保证数据
- 行业动态
- 2025-04-21
- 4
本地数据存储方案
在断网时保障数据的核心思路是将数据持久化存储在本地,待网络恢复后同步至服务器,以下是常见的本地存储方案:
存储方式 | 适用场景 | 特点 |
---|---|---|
SQLite数据库 | 结构化数据(如订单、用户信息) | 支持复杂查询,事务安全,但需手动管理数据库操作 |
Room数据库 | 结构化数据(推荐替代SQLite) | 提供抽象层,简化开发,支持LiveData观察数据变化 |
SharedPreferences | 轻量级键值对(如用户设置、状态) | 操作简单,仅适合存储少量数据 |
文件存储 | 非结构化数据(如图片、日志) | 适合二进制数据,需处理文件路径和IO异常 |
ContentProvider | 跨进程数据共享 | 通常用于系统级数据共享,开发复杂度较高 |
示例代码(Room数据库)
// 定义实体 @Entity(tableName = "user_table") data class User( @PrimaryKey val id: Int, val name: String, val lastUpdate: Long // 用于同步冲突判断 ) // 定义DAO @Dao interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertUser(user: User) @Query("SELECT FROM user_table WHERE lastUpdate > :timestamp") fun getUnsyncedUsers(timestamp: Long): LiveData<List<User>> } // 使用ViewModelScope协程插入数据 viewModelScope.launch { userDao.insertUser(user) }
网络状态监听与处理
实时监听网络状态
// 注册网络变化广播(推荐使用NetworkCallback) val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { // 网络恢复,触发同步逻辑 } override fun onLost(network: Network) { // 网络断开,提示用户或暂停网络请求 } } // 注册回调(需在Android 10+动态注册) connectivityManager.registerDefaultNetworkCallback(networkCallback)
处理网络请求策略
- 自动重试机制:使用Retrofit配合OkHttp的重试拦截器
- 离线模式切换:通过
LiveData
或Flow
监控网络状态,动态切换数据源 - 用户提示:在断网时显示本地缓存数据,并提供重试按钮
数据同步机制设计
同步队列设计
同步策略 | 适用场景 | 实现方式 |
---|---|---|
即时同步 | 对实时性要求高的操作(如支付) | 网络可用时立即上传 |
定时同步 | 非紧急数据(如日志、统计) | 使用WorkManager周期任务 |
增量同步 | 大量数据分批同步 | 按时间戳或版本号分段上传 |
冲突解决策略
- 版本号机制:每条数据携带更新时间戳,冲突时保留最新
- 唯一约束:通过主键或唯一索引避免重复插入
- 交互式合并:对重要数据弹出冲突解决对话框
同步流程示例
// 网络恢复后触发同步 fun syncData() { lifecycleScope.launch { // 1. 获取本地未同步数据 val localData = userDao.getUnsyncedUsers(System.currentTimeMillis()) // 2. 批量上传至服务器 val response = apiService.uploadData(localData) // 3. 根据返回结果更新本地状态 if (response.isSuccessful) { // 标记数据为已同步 localData.forEach { userDao.updateSyncStatus(it.id, System.currentTimeMillis()) } } else { // 处理失败逻辑(如重试或标记为错误状态) } } }
离线数据处理优化
API缓存策略
- Retrofit + OkHttp缓存:配置HTTP缓存头实现自动缓存
- 自定义缓存逻辑:对关键接口结果进行序列化存储
分页与预加载
- 使用
Paging3
库实现离线分页(需配合Room) - 在网络可用时预加载下一页数据
数据压缩与分片
- 对大文件进行分片上传(如每片1MB)
- 使用GZIP压缩JSON数据减少传输量
事务与一致性保障
本地事务管理
- Room事务:利用
@Transaction
注解保证多表操作原子性 - 手动事务:对复杂操作显式开启事务并处理回滚
分布式事务处理
- 乐观锁:通过版本号检测更新冲突
- 消息队列:使用LocalBroadcastManager或EventBus传递同步事件
相关问题与解答
Q1: 如何检测网络连接状态?
A: 推荐使用ConnectivityManager.NetworkCallback
动态监听网络变化,示例:
val request = NetworkRequest.Builder().build() connectivityManager.registerNetworkCallback(request, object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { / 网络恢复 / } override fun onLost(network: Network) { / 网络断开 / } })
Q2: SQLite和Room数据库如何选择?
A:
| 对比维度 | SQLite | Room |
|—————–|—————————-|——————————-|
| 开发效率 | 需手写SQL和Cursor处理 | 提供DAO注解,自动生成代码 |
| 编译时检查 | 无 | 支持SQL语法检查 |
| 架构适配 | 需手动处理线程和异步 | 内置支持LiveData和Coroutine |
| 最佳场景 | 简单项目或第三方库 | 复杂项目需要架构解耦 |