PeriodicWorkRequest执行过频:设置1.5小时周期却每15分钟运行
问题:PeriodicWorkRequest 设置90分钟更新间隔,实际却每15分钟执行一次
我尝试实现一个每1.5小时(90分钟)更新天气数据的Worker,使用PeriodicWorkRequestBuilder设置了时间参数,但Logcat显示Worker每15分钟就执行一次。相关代码如下:
主Activity中创建WorkRequest的代码
@RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val workRequest = PeriodicWorkRequestBuilder<WeatherUpdateWorker>( repeatInterval = 90, repeatIntervalTimeUnit = TimeUnit.MINUTES, ).setBackoffCriteria( backoffPolicy = BackoffPolicy.LINEAR, duration = Duration.ofSeconds(15) ) .build() WorkManager.getInstance(applicationContext).enqueueUniquePeriodicWork( "WeatherUpdateWork", ExistingPeriodicWorkPolicy.KEEP, workRequest ) }
WeatherUpdateWorker代码
@HiltWorker class WeatherUpdateWorker @AssistedInject constructor( private val api: WeatherService, @Assisted val context: Context, @Assisted workerParameters: WorkerParameters, private val viewModel: WeatherViewModel ): CoroutineWorker(context, workerParameters) { override suspend fun doWork(): Result { try { val response = api.getWeather() viewModel.setWeatherResults(response) val currentTime = System.currentTimeMillis() saveLastExecutionTime(currentTime) Log.d("WeatherWorker", "Success, ${currentTime}") return Result.success() } catch (e: Exception) { Log.d("WeatherWorker", "Error") return Result.retry() } } private fun saveLastExecutionTime(currentTime: Long) { val sharedPreferences = context.getSharedPreferences("weather_prefs", Context.MODE_PRIVATE) sharedPreferences.edit().putLong("last_execution_time", currentTime).apply() } }
WorkerFactory代码
@HiltAndroidApp class Application : Application(), Configuration.Provider { @Inject lateinit var workerFactory: CustomWorkerFactory override fun getWorkManagerConfiguration() = Configuration.Builder() .setMinimumLoggingLevel(Log.DEBUG) .setWorkerFactory(workerFactory) .build() } class CustomWorkerFactory @Inject constructor(private val api: WeatherService, private val viewModel: WeatherViewModel): WorkerFactory() { override fun createWorker( appContext: Context, workerClassName: String, workerParameters: WorkerParameters ): ListenableWorker? = WeatherUpdateWorker(api, appContext, workerParameters, viewModel) }
解决方案
1. 排查Worker执行失败导致的重试
先查看Logcat中的WeatherWorker日志,如果频繁出现Error,说明doWork()方法持续抛出异常,返回Result.retry()后,WorkManager会按照退避策略不断重试:
- 检查
api.getWeather()的网络请求是否正常:确认网络权限配置正确、接口地址/参数无误、服务器返回正常。 - 移除Worker中的ViewModel依赖:ViewModel是绑定UI组件生命周期的,Worker作为后台任务持有ViewModel会导致生命周期不匹配,极易引发异常。建议Worker直接将数据存入本地存储(如SharedPreferences、Room),再由UI层读取展示。
2. 替换已存在的旧WorkRequest
如果之前创建过15分钟间隔的WorkRequest,使用ExistingPeriodicWorkPolicy.KEEP会保留旧任务,不会替换为新的90分钟间隔配置。将策略改为REPLACE,确保新配置生效:
WorkManager.getInstance(applicationContext).enqueueUniquePeriodicWork( "WeatherUpdateWork", ExistingPeriodicWorkPolicy.REPLACE, // 替换旧任务 workRequest )
3. 修复Worker的ViewModel依赖问题
修改Worker,去掉ViewModel注入,直接处理数据存储:
@HiltWorker class WeatherUpdateWorker @AssistedInject constructor( private val api: WeatherService, @Assisted val context: Context, @Assisted workerParameters: WorkerParameters ): CoroutineWorker(context, workerParameters) { override suspend fun doWork(): Result { return try { val response = api.getWeather() // 将天气数据存入SharedPreferences saveWeatherData(response) val currentTime = System.currentTimeMillis() saveLastExecutionTime(currentTime) Log.d("WeatherWorker", "Success, ${currentTime}") Result.success() } catch (e: Exception) { Log.e("WeatherWorker", "执行失败", e) // 打印完整异常信息,方便排查 Result.retry() } } private fun saveWeatherData(response: WeatherResponse) { val sharedPreferences = context.getSharedPreferences("weather_prefs", Context.MODE_PRIVATE) val gson = Gson() val json = gson.toJson(response) sharedPreferences.edit().putString("weather_data", json).apply() } private fun saveLastExecutionTime(currentTime: Long) { val sharedPreferences = context.getSharedPreferences("weather_prefs", Context.MODE_PRIVATE) sharedPreferences.edit().putLong("last_execution_time", currentTime).apply() } }
同时更新CustomWorkerFactory,移除ViewModel参数:
class CustomWorkerFactory @Inject constructor(private val api: WeatherService): WorkerFactory() { override fun createWorker( appContext: Context, workerClassName: String, workerParameters: WorkerParameters ): ListenableWorker? = WeatherUpdateWorker(api, appContext, workerParameters) }
4. 显式配置flexInterval(可选)
当repeatInterval >= 15分钟时,WorkManager默认的flexInterval为15分钟,这意味着Worker会在每个90分钟周期的最后15分钟窗口内执行。如果需要更精确的执行窗口控制,可以显式设置flexInterval:
val workRequest = PeriodicWorkRequestBuilder<WeatherUpdateWorker>( repeatInterval = 90, repeatIntervalTimeUnit = TimeUnit.MINUTES, flexInterval = 10, // 自定义flex间隔为10分钟 flexIntervalTimeUnit = TimeUnit.MINUTES ).setBackoffCriteria( backoffPolicy = BackoffPolicy.LINEAR, duration = Duration.ofSeconds(15) ).build()
内容的提问来源于stack exchange,提问作者James Taufa
相关产品推荐
相关产品推荐

