如何推送API获取的数据?基于ViewModel的每小时定时通知实现咨询
实现每小时定时推送API数据通知的方案
核心思路
要实现这个需求,核心是用WorkManager处理后台定时任务(适配Android后台限制),抽离API数据获取逻辑到Repository层(让ViewModel和后台任务复用),最后在任务中获取数据并构建通知推送。
1. 配置定时任务(WorkManager)
Android 8+对后台定时任务有严格限制,推荐用WorkManager来实现每小时执行的任务,它会自动适配系统的后台策略:
步骤1:创建后台Worker类
这个类负责执行定时任务:获取API数据、推送通知。
class DataNotificationWorker( context: Context, params: WorkerParameters ) : CoroutineWorker(context, params) { private val repository = DataRepository() // 复用你的数据仓库 private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager override suspend fun doWork(): Result { return try { // 1. 获取API数据 val apiData = repository.getLatestData() // 2. 构建并发送通知 sendNotification(apiData) Result.success() } catch (e: Exception) { // 失败后重试(可选,可设置重试次数或延迟) Result.retry() } } private fun sendNotification(data: ApiData) { // Android 8+ 必须创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( "data_notification_channel", "API数据通知", NotificationManager.IMPORTANCE_DEFAULT ).apply { description = "每小时推送最新API数据" } notificationManager.createNotificationChannel(channel) } // 构建通知内容,直接填入API返回的数据 val notification = NotificationCompat.Builder(applicationContext, "data_notification_channel") .setContentTitle("最新API更新:${data.title}") .setContentText("详情:${data.detail} | 更新时间:${data.updateTime}") .setSmallIcon(R.drawable.ic_notification) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() // 用时间戳作为通知ID,避免重复通知被覆盖 notificationManager.notify(System.currentTimeMillis().toInt(), notification) } }
步骤2:启动定时任务
在App启动时(比如Application类或主Activity的onCreate方法),调度每小时执行的任务:
val periodicWorkRequest = PeriodicWorkRequestBuilder<DataNotificationWorker>(1, TimeUnit.HOURS) .setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) // 仅在有网络时执行 .build()) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "DataNotificationWork", ExistingPeriodicWorkPolicy.KEEP, // 如果已有任务存在,保留原任务 periodicWorkRequest )
2. 抽离API数据获取逻辑(Repository层)
ViewModel依赖UI生命周期,后台任务不能直接使用ViewModel,因此需要把API请求逻辑抽成独立的Repository层,让ViewModel和后台Worker复用:
class DataRepository { private val apiService = RetrofitClient.create(ApiService::class.java) // 封装API请求方法 suspend fun getLatestData(): ApiData { return apiService.fetchLatestData() // 替换为你的实际API请求 } }
ViewModel也通过这个Repository获取数据:
class DataViewModel(private val repository: DataRepository) : ViewModel() { private val _data = MutableLiveData<ApiData>() val data: LiveData<ApiData> = _data fun fetchData() { viewModelScope.launch { try { _data.value = repository.getLatestData() } catch (e: Exception) { // 处理UI层的错误逻辑 } } } }
3. 权限配置
在AndroidManifest.xml中添加必要权限:
<!-- 网络权限(获取API数据需要) --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Android 13+ 通知权限,需动态申请 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 12+ 精确闹钟权限,用于更稳定的定时执行 --> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
Android 13+设备上,需要在代码中动态申请POST_NOTIFICATIONS权限,否则通知无法显示。
关键注意事项
- 禁止依赖ViewModel:后台任务不能持有ViewModel实例,必须通过Repository层获取数据。
- 错误处理:在Worker中捕获API请求异常,可设置重试次数或延迟,避免任务无限重试。
- 通知渠道:Android 8+必须创建通知渠道,否则通知无法正常显示。
- 网络约束:通过WorkManager的Constraints设置仅在有网络时执行任务,避免无网时浪费资源。
内容的提问来源于stack exchange,提问作者Talha K.
相关产品推荐
相关产品推荐

