WorkManager vs Flow 适用场景分析

1. WorkManager 适用场景

1.1 需要保证执行的任务

场景:数据同步、日志上传、文件下载

Kotlin 复制代码
// 场景:用户上传照片,需要保证最终上传成功

class PhotoUploadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {

        return try {

            val photoPath = inputData.getString("photo_path") ?: return Result.failure()

            

            // 上传照片

            uploadPhoto(photoPath)

            

            // 即使应用被杀死,任务也会在系统允许时重试

            Result.success()

        } catch (e: Exception) {

            // 失败时会自动重试

            Result.retry()

        }

    }

}

// 使用 WorkManager

val uploadWork = OneTimeWorkRequestBuilder<PhotoUploadWorker>()

    .setInputData(Data.Builder().putString("photo_path", path).build())

    .setConstraints(

        Constraints.Builder()

            .setRequiredNetworkType(NetworkType.CONNECTED)

            .build()

    )

    .build()

WorkManager.getInstance(context).enqueue(uploadWork)

为什么选择 WorkManager:

  • ✅ 应用被杀死后任务仍会执行
  • ✅ 系统会自动处理重试
  • ✅ 支持网络、充电等约束条件

1.2 周期性任务

场景:定时同步、定时清理、定时备份

Kotlin 复制代码
// 场景:每天凌晨2点同步用户数据

val syncWork = PeriodicWorkRequestBuilder<DataSyncWorker>(

    1, TimeUnit.DAYS // 每天执行一次

).setConstraints(

    Constraints.Builder()

        .setRequiredNetworkType(NetworkType.CONNECTED)

        .setRequiresDeviceIdle(true) // 设备空闲时执行

        .build()

).build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(

    "daily_sync",

    ExistingPeriodicWorkPolicy.KEEP,

    syncWork

)

为什么选择 WorkManager:

  • ✅ 系统保证周期性执行
  • ✅ 不受应用生命周期影响
  • ✅ 支持系统级约束(空闲、充电等)

1.3 后台任务(应用不可见时)

场景:数据预处理、缓存清理、日志收集

Kotlin 复制代码
// 场景:应用进入后台时收集使用数据

class AnalyticsWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {

        return try {

            // 收集用户行为数据

            collectUserBehavior()

            

            // 上传到服务器

            uploadAnalytics()

            

            Result.success()

        } catch (e: Exception) {

            Result.failure()

        }

    }

}

为什么选择 WorkManager:

  • ✅ 应用在后台时仍能执行
  • ✅ 系统会优化执行时机
  • ✅ 不会影响用户体验

2. Flow 适用场景

2.1 实时数据流

场景:网络请求、数据库查询、传感器数据

Kotlin 复制代码
// 场景:实时获取用户位置

class LocationRepository {

    fun getLocationUpdates(): Flow<Location> = flow {

        locationManager.requestLocationUpdates(

            LocationManager.GPS_PROVIDER,

            1000L, // 1秒更新一次

            10f

        ) { location ->

            emit(location)

        }

    }

    .flowOn(Dispatchers.IO)

}

// 在 ViewModel 中使用

class LocationViewModel : ViewModel() {

    private val _location = MutableStateFlow<Location?>(null)

    val location: StateFlow<Location?> = _location.asStateFlow()

    

    fun startLocationUpdates() {

        locationRepository.getLocationUpdates()

            .onEach { location ->

                _location.value = location

            }

            .launchIn(viewModelScope)

    }

}

为什么选择 Flow:

  • ✅ 实时响应数据变化
  • ✅ 易于取消和重新订阅
  • ✅ 支持背压处理

2.2 UI 状态管理

场景:界面状态、用户输入、动画进度

Kotlin 复制代码
// 场景:搜索功能

class SearchViewModel : ViewModel() {

    private val _searchQuery = MutableStateFlow("")

    val searchQuery: StateFlow<String> = _searchQuery.asStateFlow()

    

    private val _searchResults = MutableStateFlow<List<Item>>(emptyList())

    val searchResults: StateFlow<List<Item>> = _searchResults.asStateFlow()

    

    fun search(query: String) {

        _searchQuery.value = query

        

        // 防抖搜索

        searchQuery

            .debounce(300) // 300ms 防抖

            .filter { it.length >= 2 } // 至少2个字符

            .flatMapLatest { query ->

                searchRepository.search(query)

            }

            .onEach { results ->

                _searchResults.value = results

            }

            .launchIn(viewModelScope)

    }

}

为什么选择 Flow:

  • ✅ 响应式编程
  • ✅ 支持复杂的数据转换
  • ✅ 易于测试

2.3 网络请求和数据处理

场景:API 调用、数据转换、缓存

Kotlin 复制代码
// 场景:获取用户信息并处理

class UserRepository {

    fun getUserInfo(userId: String): Flow<UserInfo> = flow {

        // 先从缓存获取

        val cachedUser = userCache.getUser(userId)

        emit(cachedUser)

        

        // 从网络获取最新数据

        val networkUser = apiService.getUser(userId)

        emit(networkUser)

        

        // 更新缓存

        userCache.saveUser(networkUser)

    }

    .catch { e ->

        // 网络失败时使用缓存数据

        val cachedUser = userCache.getUser(userId)

        if (cachedUser != null) {

            emit(cachedUser)

        } else {

            throw e

        }

    }

    .flowOn(Dispatchers.IO)

}

为什么选择 Flow:

  • ✅ 支持多数据源
  • ✅ 易于处理错误
  • ✅ 支持数据转换

3. 选择指南

3.1 选择 WorkManager 的场景

// ✅ 需要保证执行的任务

  • 文件上传/下载

  • 数据同步

  • 日志上传

  • 备份任务

// ✅ 周期性任务

  • 定时清理

  • 定时同步

  • 定时备份

// ✅ 应用不可见时的任务

  • 数据预处理

  • 缓存清理

  • 后台分析

// ✅ 需要系统约束的任务

  • 仅在充电时执行

  • 仅在 WiFi 下执行

  • 仅在设备空闲时执行

3.2 选择 Flow 的场景

// ✅ 实时数据流

  • 网络请求响应

  • 数据库变化

  • 传感器数据

  • 用户输入

// ✅ UI 状态管理

  • 界面状态

  • 用户交互

  • 动画进度

// ✅ 数据处理管道

  • 数据转换

  • 数据过滤

  • 数据合并

// ✅ 响应式编程

  • 事件驱动

  • 状态管理

  • 数据绑定


4. 实际项目中的选择策略

4.1 电商应用示例

Kotlin 复制代码
// 使用 WorkManager 的场景

class OrderSyncWorker : Worker() {

    override fun doWork(): Result {

        // 同步订单状态

        syncOrderStatus()

        return Result.success()

    }

}

// 使用 Flow 的场景

class ProductViewModel : ViewModel() {

    private val _products = MutableStateFlow<List<Product>>(emptyList())

    val products: StateFlow<List<Product>> = _products.asStateFlow()

    

    fun searchProducts(query: String) {

        productRepository.searchProducts(query)

            .onEach { products ->

                _products.value = products

            }

            .launchIn(viewModelScope)

    }

}

4.2 社交媒体应用示例

Kotlin 复制代码
 

// 使用 WorkManager 的场景

class MessageSyncWorker : Worker() {

    override fun doWork(): Result {

        // 同步离线消息

        syncOfflineMessages()

        return Result.success()

    }

}

// 使用 Flow 的场景

class ChatViewModel : ViewModel() {

    private val _messages = MutableStateFlow<List<Message>>(emptyList())

    val messages: StateFlow<List<Message>> = _messages.asStateFlow()

    

    fun observeMessages(chatId: String) {

        messageRepository.getMessages(chatId)

            .onEach { messages ->

                _messages.value = messages

            }

            .launchIn(viewModelScope)

    }

}

5. 总结

选择 WorkManager 当:

  • 需要保证任务最终执行
  • 任务需要在应用不可见时执行
  • 需要系统级约束条件
  • 周期性任务
  • 应用被杀死后仍需执行的任务

选择 Flow 当:

  • 实时数据流处理
  • UI 状态管理
  • 用户交互响应
  • 数据处理管道
  • 需要取消和重新订阅的场景

最佳实践:

  • 在同一个项目中,WorkManager 和 Flow 可以结合使用
  • WorkManager 负责后台任务调度
  • Flow 负责实时数据流和 UI 状态管理
  • 根据具体需求选择最合适的方案

这样选择可以确保应用的稳定性和用户体验!