当前位置:首页 > 行业动态 > 正文

安卓开发定时获取网络数据

实现定时任务的核心组件

安卓中实现定时任务主要依赖以下组件:

组件 适用场景 最小API支持
AlarmManager 精确定时唤醒(需处理系统杀进程问题) API 1
JobScheduler 系统级调度(API 21+) API 21
WorkManager 兼容各版本、可靠执行(推荐) API 14
Handler.postDelayed 短时间延迟任务(不适用于跨进程/被杀情况) API 1
RxJava/Coroutine 基于时间轴的轮询(需配合前台服务)

网络请求最佳实践

  1. 网络层封装
    建议使用Retrofit+OkHttp组合,配置示例:

    val retrofit = Retrofit.Builder()
     .baseUrl("https://api.example.com")
     .addConverterFactory(GsonConverterFactory.create())
     .client(OkHttpClient.Builder()
         .readTimeout(10, TimeUnit.SECONDS)
         .build())
     .build()
  2. 协程异步处理
    使用Kotlin协程简化异步代码:

    viewModelScope.launch {
     try {
         val data = withContext(Dispatchers.IO) {
             apiService.getData()
         }
         // 更新UI
     } catch (e: Exception) {
         // 错误处理
     }
    }

定时任务与网络请求整合方案

方案对比表

方案 可靠性 存活能力 开发难度 适用场景
AlarmManager+IntentService 简单 简单定时任务(需保活)
JobScheduler+Coroutine 中等 Android 7.0+系统级调度
WorkManager+Coroutine 简单 全版本兼容、后台可靠执行
RxJava轮询 复杂 短周期实时性要求场景

推荐方案:WorkManager实现

// 定义Worker类
class FetchDataWorker(appContext: Context, params: WorkerParameters) :
    CoroutineWorker(appContext, params) {
    override suspend fun doWork(): Result {
        return try {
            // 执行网络请求
            val data = apiService.getData()
            // 持久化或发送广播
            Result.success()
        } catch (e: Exception) {
            Result.retry()
        }
    }
}
// 调度任务
val workRequest = OneTimeWorkRequestBuilder<FetchDataWorker>()
    .setInitialDelay(1, TimeUnit.HOURS) // 初始延迟
    .setPeriodic(1, TimeUnit.HOURS) // 周期执行
    .build()
WorkManager.getInstance(context).enqueue(workRequest)

关键注意事项

  1. 进程被杀处理

    • WorkManager会自动恢复未完成的任务
    • 需在AndroidManifest添加:
      <service android:name="androidx.work.impl.background.systemalarm.RescheduleReceiver"
          android:exported="false" />
  2. 网络状态监听

    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val network = connectivityManager.activeNetworkInfo
    if (network != null && network.isConnected) {
        // 执行网络请求
    } else {
        // 延迟重试
        WorkManager.getInstance(context).enqueue(workRequest.setBackoffCriteria(BackoffPolicy.LINEAR, 5, TimeUnit.MINUTES))
    }
  3. 电量优化策略

    • 设置合理周期(建议≥15分钟)
    • 使用setConstraints限制只在充电/非省电模式运行:
      val constraints = Constraints.Builder()
          .setRequiresCharging(true) // 充电时执行
          .build()

完整代码示例

// Build.gradle依赖
implementation "androidx.work:work-runtime-ktx:2.7.1"
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutine-core:1.6.1"
// Worker实现类
class DataSyncWorker(appContext: Context, params: WorkerParameters) :
    CoroutineWorker(appContext, params) {
    private val apiService: ApiService by lazy {
        Retrofit.Builder()
            .baseUrl("https://api.example.com")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
    override suspend fun doWork(): Result {
        return withContext(Dispatchers.IO) {
            try {
                val response = apiService.fetchData()
                if (response.isSuccessful) {
                    // 处理数据并持久化
                    Result.success()
                } else {
                    Result.retry()
                }
            } catch (e: Exception) {
                Result.retry()
            }
        }
    }
}
// 调度逻辑
fun schedulePeriodicTask(context: Context) {
    val workRequest = PeriodicWorkRequestBuilder<DataSyncWorker>(1, TimeUnit.HOURS)
        .setConstraints(Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresCharging(false)
            .build())
        .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
        .build()
    WorkManager.getInstance(context).enqueue(workRequest)
}

相关问题与解答

Q1:如何处理WorkManager任务被系统杀死后自动恢复?

A:WorkManager通过系统提供的JobScheduler(API 23+)或AlarmManager(API <23)实现持久化调度,当应用进程被杀死时,系统会保留调度信息,在进程重建后自动执行未完成的任务,开发者无需额外处理,但需确保Worker类实现@Expose注解字段(如果使用Parcelable参数)。

Q2:如何在定时任务中更新UI或发送通知?

A:由于Worker运行在后台线程,直接更新UI会导致异常,推荐做法:

  1. 发送广播到前端:
    context.sendBroadcast(Intent("ACTION_DATA_UPDATED").apply {
        putExtra("data", resultData)
    })
  2. 使用LiveDataViewModel观察数据变化(需结合前台Service)
  3. 显示通知:
    NotificationManagerCompat.from(context).notify(1, notificationBuilder.build())
0