You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何推送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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 09:45:27