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

Android MVVM应用实现10秒间隔API轮询(学习用途)

问题描述

我正在开发一款用于学习的简易Android MVVM应用,需要每10秒从REST API获取数据,即使应用被杀死也需正常执行。了解到WorkManager默认最小重复间隔为15分钟,无法满足需求。以下是我的简化代码结构:

现有代码结构

ApiInterface

interface ApiInterface {
    @GET("search?country=India")
    suspend fun getUniversities() : Response<University>
}

ApiUtilities

object ApiUtilities {
    val BASE_URL = "http://universities.hipolabs.com/"

    fun getInstance() : Retrofit {
        return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
}

Repository

class UniversityRepository(private val apiInterface: ApiInterface) {

    private val universityLiveData = MutableLiveData<University>()

    val university : LiveData<University>
        get() = universityLiveData

    suspend fun getUniversities() {
        val result = apiInterface.getUniversities()
        if(result.body() != null) {
            universityLiveData.postValue(result.body())
        }
    }
}

ViewModel

class UniversityViewModel(private val universityRepository: UniversityRepository): ViewModel() {

    init {
        viewModelScope.launch(Dispatchers.IO) {
            universityRepository.getUniversities()
        }
    }

    val university: LiveData<University>
        get() = universityRepository.university
}
解决方案与指导

首先明确:Android系统对后台任务有严格限制,尤其是Android 8.0(API 26)及以上版本,应用被杀后要实现10秒级轮询几乎没有可靠的官方方案——系统会主动限制这类高频后台操作以节省电量。以下分场景给出可行方案:

1. 应用在前台/后台(未被杀)时的10秒轮询

这种场景可以用协程结合ViewModel实现,简单直接且无内存泄漏风险:

修改ViewModel实现轮询逻辑

class UniversityViewModel(private val universityRepository: UniversityRepository): ViewModel() {

    val university: LiveData<University>
        get() = universityRepository.university

    init {
        startPolling()
    }

    private fun startPolling() {
        viewModelScope.launch(Dispatchers.IO) {
            while (isActive) {
                universityRepository.getUniversities()
                delay(10000) // 10秒间隔
            }
        }
    }
}
  • 优点:依托viewModelScope,ViewModel销毁时协程自动取消,不会造成内存泄漏;代码实现简单
  • 局限:应用退到后台后,系统可能在短时间内回收进程导致轮询中断;应用被杀后完全停止

2. 尝试实现应用被杀后的高频轮询(不推荐,兼容性差)

如果一定要尝试应用被杀后的10秒轮询,只能通过前台服务+协程的方式,但效果受系统版本和厂商定制影响极大:

步骤1:创建前台服务

前台服务会在通知栏显示持续通知,系统不会轻易杀死它:

class PollingForegroundService : Service() {
    private val coroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // 创建前台通知(需先在Manifest注册通知渠道)
        val notification = NotificationCompat.Builder(this, "POLLING_CHANNEL")
            .setContentTitle("正在获取数据")
            .setContentText("每10秒更新一次")
            .setSmallIcon(R.drawable.ic_notification)
            .build()

        startForeground(1, notification)

        // 启动轮询
        coroutineScope.launch {
            val apiInterface = ApiUtilities.getInstance().create(ApiInterface::class.java)
            val repository = UniversityRepository(apiInterface)
            while (isActive) {
                repository.getUniversities()
                delay(10000)
            }
        }

        return START_STICKY // 服务被杀死后尝试重启
    }

    override fun onBind(intent: Intent?): IBinder? = null

    override fun onDestroy() {
        super.onDestroy()
        coroutineScope.cancel()
    }
}

步骤2:在Manifest注册服务与权限

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ 必填 -->

<application ...>
    <service android:name=".PollingForegroundService" />
</application>

步骤3:启动服务

在Activity或ViewModel中触发启动:

val intent = Intent(context, PollingForegroundService::class.java)
ContextCompat.startForegroundService(context, intent)
  • 注意:部分厂商定制系统(如小米、华为)仍可能在应用被杀后强制停止前台服务;高频轮询会大幅消耗电量,严重影响用户体验

3. 更合理的替代方案(推荐)

鉴于Android系统的限制,10秒级轮询本身就不符合后台操作的最佳实践,推荐以下替代方案:

  • 改用WebSocket:如果API支持WebSocket,用长连接代替轮询,服务器主动推送数据,既实时又省电
  • 调整轮询间隔:将间隔调整到15分钟以上,用WorkManager实现可靠的后台轮询(官方推荐的后台任务方案)
  • 使用FCM推送:让服务器通过Firebase Cloud Messaging主动给设备推送数据更新,无需客户端主动轮询
关键注意事项
  • 高频后台轮询会严重消耗设备电量,极易引发用户反感甚至卸载应用
  • Android 12(API 31)及以上对前台服务的限制更严格,部分场景下无法启动
  • 应用被杀后,系统没有保证高频任务持续运行的机制,所有方案都存在兼容性问题

内容的提问来源于stack exchange,提问作者Sidharth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:01:36