如何实现MySQL到Android Room的数据自动同步
实现Web到Android Room的库存自动同步(基于Retrofit2)
以下是针对你的需求的几种实用实现方案,均基于Retrofit2展开,适合Android新手快速落地:
方案1:定时轮询(最易上手)
通过定期发起Retrofit请求拉取后端更新的库存数据,同步到Room,是新手最容易实现的方案。
步骤:
后端新增增量查询接口
接口需要支持传入上次同步的时间戳,返回该时间之后更新的库存记录(依赖MySQL表中的update_time字段,每次数据修改自动更新该字段)。
Retrofit接口定义示例:interface InventoryApi { // 传入上次同步时间,返回更新后的库存列表 @GET("api/inventory/updated") suspend fun getUpdatedInventories(@Query("last_sync") lastSyncTime: Long): Response<List<Inventory>> }用WorkManager实现可靠定时任务
Android后台限制较多,WorkManager是官方推荐的定时任务方案,能适配不同版本的后台规则:class InventorySyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { return try { // 1. 获取Retrofit实例 val api = RetrofitClient.getInstance().create(InventoryApi::class.java) // 2. 从SharedPreferences取上次同步时间 val lastSyncTime = getSharedPreferences("sync_prefs", Context.MODE_PRIVATE) .getLong("last_sync_time", 0) // 3. 请求增量数据 val response = api.getUpdatedInventories(lastSyncTime) if (response.isSuccessful) { response.body()?.let { updatedList -> // 4. 同步到Room val dao = AppDatabase.getInstance(applicationContext).inventoryDao() dao.upsertAll(updatedList) // 5. 保存本次同步时间 getSharedPreferences("sync_prefs", Context.MODE_PRIVATE) .edit() .putLong("last_sync_time", System.currentTimeMillis()) .apply() } Result.success() } else { // 请求失败,稍后重试 Result.retry() } } catch (e: Exception) { // 捕获网络异常等,避免任务崩溃 Result.failure() } } }启动定时任务
在应用启动时(比如Application类或MainActivity的onCreate)初始化定时同步:val syncRequest = PeriodicWorkRequestBuilder<InventorySyncWorker>(15, TimeUnit.MINUTES) .setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) // 仅在联网时同步 .build()) .build() WorkManager.getInstance(this).enqueueUniquePeriodicWork( "InventorySync", ExistingPeriodicWorkPolicy.REPLACE, syncRequest )Room中定义Upsert方法
Room的@Upsert注解会自动判断数据是新增还是更新,无需手动区分:@Dao interface InventoryDao { @Upsert suspend fun upsertAll(inventories: List<Inventory>) }
方案2:Webhook触发的即时同步(更高效)
如果需要实时性更高的同步,可以让Web端在修改MySQL后,通过推送通知触发Android端立即拉取数据,再用Retrofit完成同步。
步骤:
Web端触发通知
Web端修改库存后,调用第三方推送服务(如FCM)给Android设备发送通知,告知有数据更新。Android端监听推送并同步
实现Firebase消息监听服务,收到通知后立即发起Retrofit请求同步数据:class InventoryMessagingService : FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) // 判断是否是库存更新通知 if (remoteMessage.data["event"] == "inventory_change") { // 在IO线程执行同步 CoroutineScope(Dispatchers.IO).launch { syncInventory() } } } private suspend fun syncInventory() { // 复用方案1中的同步逻辑 val api = RetrofitClient.getInstance().create(InventoryApi::class.java) val lastSyncTime = getSharedPreferences("sync_prefs", Context.MODE_PRIVATE) .getLong("last_sync_time", 0) val response = api.getUpdatedInventories(lastSyncTime) if (response.isSuccessful) { response.body()?.let { val dao = AppDatabase.getInstance(applicationContext).inventoryDao() dao.upsertAll(it) getSharedPreferences("sync_prefs", Context.MODE_PRIVATE) .edit() .putLong("last_sync_time", System.currentTimeMillis()) .apply() } } } }权限配置
Android 13+需要申请POST_NOTIFICATIONS权限,才能接收推送通知。
关键优化点
- 增量同步:始终只拉取上次同步后更新的数据,避免全量传输浪费带宽和时间
- 数据一致性:给MySQL库存表添加
version字段,更新时校验版本号,防止并发修改导致的数据冲突 - 异常处理:Retrofit请求必须包裹try-catch,处理网络异常、接口错误等情况
- 后台适配:避免用Timer或Handler实现定时任务,WorkManager能自动适配Android后台限制
内容的提问来源于stack exchange,提问作者Emiliano Cahayon
相关产品推荐
相关产品推荐

