在安卓应用中,定时同步数据库数据常用于以下场景:
技术组件 | 功能描述 | 适用场景 |
---|---|---|
WorkManager | 兼容安卓版本的定时/周期性任务调度框架,支持网络状态、电量等约束条件 | 需要可靠执行的定时同步任务 |
Room + LiveData | 本地数据库存储与数据变化监听 | 数据变更后自动触发同步 |
Retrofit | 网络请求封装,支持与服务器API交互 | 数据传输至服务器 |
SyncAdapter | 安卓原生同步框架,支持账户认证与周期同步(已过时,建议优先用WorkManager) | 旧项目兼容或复杂认证场景 |
Room
的LiveData
监听本地数据表变化。WorkManager
的周期性任务)。同步类型 | 说明 | 实现方式 |
---|---|---|
增量同步 | 仅同步自上次同步后变更的数据 | 通过时间戳或版本号标记变更记录 |
全量同步 | 同步全部数据(适用于首次同步或冲突修复) | 直接覆盖或合并策略 |
双向同步 | 本地与服务器数据双向更新 | 使用唯一标识(如UUID)匹配冲突 |
version
字段,冲突时比较版本号。// WorkManager implementation "androidx.work:work-runtime-ktx:2.7.1" // Room implementation "androidx.room:room-runtime:2.5.1" annotationProcessor "androidx.room:room-compiler:2.5.1" kapt "androidx.room:room-compiler:2.5.1" // 如果使用Kotlin // Retrofit implementation "com.squareup.retrofit2:retrofit:2.9.5" implementation "com.squareup.retrofit2:converter-gson:2.9.5"
@Entity(tableName = "data_table") data class DataEntity( @PrimaryKey val id: String, val content: String, val timestamp: Long, // 用于同步判断 val syncStatus: Int = 0 // 0=未同步, 1=已同步 ) @Dao interface DataDao { @Query("SELECT FROM data_table WHERE syncStatus = 0") fun getUnsyncedData(): LiveData<List<DataEntity>> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAll(data: List<DataEntity>) @Update suspend fun updateSyncStatus(data: DataEntity) }
class SyncWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) { override suspend fun doWork(): Result { val database = AppDatabase.getInstance(applicationContext) val unsyncedData = database.dataDao().getUnsyncedData().valueOrEmpty() if (unsyncedData.isEmpty()) return Result.success() return try { // 调用API上传数据 val response = Retrofit.Builder() .baseUrl("https://yourserver.com/") .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) .uploadData(unsyncedData) if (response.isSuccessful) { // 更新本地状态为已同步 unsyncedData.forEach { it.syncStatus = 1 database.dataDao().updateSyncStatus(it) } Result.success() } else { Result.retry() // 触发重试 } } catch (e: Exception) { Result.retry() } } }
val workRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS) // 每小时执行一次 .setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) // 仅在网络可用时执行 .build()) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "DataSync", // 任务唯一标识 ExistingPeriodicWorkPolicy.KEEP, // 如果存在则保留原任务 workRequest )
Constraints
限制仅在Wi-Fi网络下同步,或通过NetworkRequest
动态监听网络状态。.setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) // 仅Wi-Fi/蜂窝网络 .build())
WorkManager
的Backoff
策略减少失败时的重试频率。val backoffPolicy = BackoffPolicy.LINEAR // 线性退避(1分钟, 2分钟, 4分钟...) val workRequest = OneTimeWorkRequestBuilder<SyncWorker>() .setBackoffCriteria(BackoffPolicy.LINEAR, 10_000, TimeUnit.MILLISECONDS) .build()
database.runInTransaction { val data = dataDao.getUnsyncedData() // 获取未同步数据 // 执行同步逻辑 }
解答:
WorkManager
通过系统JobScheduler
或AlarmManager
实现,即使应用被杀死,系统仍会唤醒应用执行任务。AndroidManifest.xml
中声明.provider
: <provider android:name="androidx.startup.InitializationProvider" android:exported="false" />
解答:
WorkManager
默认会按Backoff
策略重试失败任务。doWork()
中返回Result.retry()
,并设置最大重试次数: val workRequest = OneTimeWorkRequestBuilder<SyncWorker>() .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30_000, TimeUnit.MILLISECONDS) // 最多重试3次 .build()
Room
数据库),待网络恢复后重新触发同步