多模块Android项目中非持久化长任务跨模块同步进度的方案咨询
解决方案建议
针对你的多模块长任务需求,推荐以下两种适配场景的方案,均符合模块隔离规则且规避已尝试方案的问题:
方案1:共享模块单例协程容器 + Flow 进度传递
利用共享模块的全局可访问性,创建单例类管理长任务与进度分发,直接传递大对象且保证任务在进程存活期间持续运行。
实现步骤
- 共享模块中定义任务管理单例
class LongTaskManager private constructor() { // 独立协程作用域,避免任务失败影响其他逻辑 private val taskScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) // 用StateFlow分发进度,支持多组件订阅 private val _progressFlow = MutableStateFlow<Int?>(null) val progressFlow: StateFlow<Int?> = _progressFlow // 启动SDK任务,直接接收大参数 fun startSdkTask(largeParam: Any) { // 先取消已有任务避免重复执行 taskScope.coroutineContext.cancelChildren() taskScope.launch { // 调用SDK方法,假设SDK提供进度回调 sdkMethodWithProgress(largeParam) { progress -> _progressFlow.value = progress } // 任务结束后重置进度状态 _progressFlow.value = null } } // 手动取消任务 fun cancelCurrentTask() { taskScope.coroutineContext.cancelChildren() _progressFlow.value = null } companion object { // 线程安全的单例初始化 val instance: LongTaskManager by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { LongTaskManager() } } }
- Module A 启动任务
直接调用共享模块的单例方法,无需跨模块传递大对象:
// 在Module A的业务逻辑中 LongTaskManager.instance.startSdkTask(yourLargeObject)
- Module B 订阅进度
在Module B的Fragment中,结合生命周期收集进度:
// 在Fragment的onViewCreated方法中 lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { LongTaskManager.instance.progressFlow.collect { progress -> progress?.let { // 更新UI展示进度 updateProgressUI(it) } } } }
方案优势
- 直接传递大对象,规避WorkManager参数限制与全局存储的安全风险
- 协程作用域绑定进程,页面切换不影响任务运行
- 进度通过Flow分发,符合多模块隔离规则,仅共享模块暴露访问入口
方案2:共享模块应用级ViewModel
创建与应用进程生命周期绑定的ViewModel,利用Android架构组件的生命周期管理能力,更贴合Jetpack规范。
实现步骤
- 共享模块中定义应用级ViewModel
class AppLevelTaskViewModel(application: Application) : AndroidViewModel(application) { private val _progressFlow = MutableStateFlow<Int?>(null) val progressFlow: StateFlow<Int?> = _progressFlow private var sdkJob: Job? = null fun startSdkTask(largeParam: Any) { sdkJob?.cancel() sdkJob = viewModelScope.launch(Dispatchers.IO) { sdkMethodWithProgress(largeParam) { progress -> _progressFlow.value = progress } _progressFlow.value = null } } fun cancelTask() { sdkJob?.cancel() _progressFlow.value = null } }
- 封装ViewModel获取工具(共享模块)
避免各模块重复编写获取逻辑:
object ViewModelHelper { fun getAppLevelViewModel(activity: Activity): AppLevelTaskViewModel { return ViewModelProvider( activity.applicationContext as ViewModelStoreOwner, ViewModelProvider.AndroidViewModelFactory.getInstance(activity.application) )[AppLevelTaskViewModel::class.java] } }
- Module A 启动任务
val appViewModel = ViewModelHelper.getAppLevelViewModel(requireActivity()) appViewModel.startSdkTask(yourLargeObject)
- Module B 订阅进度
val appViewModel = ViewModelHelper.getAppLevelViewModel(requireActivity()) lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { appViewModel.progressFlow.collect { progress -> progress?.let { updateProgressUI(it) } } } }
方案优势
- ViewModel生命周期与应用进程绑定,页面切换不会被销毁
- 利用
viewModelScope自动处理协程生命周期,减少内存泄漏风险 - 大对象直接传递,无需额外存储
注意事项
- 任务取消:在用户退出应用或主动终止任务时,调用
cancel方法释放资源 - 进程回收:因需求为非持久化任务,若系统回收应用进程,任务终止符合预期,无需额外处理
- 线程安全:单例与ViewModel的实现均保证线程安全,避免多线程调用冲突
内容的提问来源于stack exchange,提问作者ndn
相关产品推荐
相关产品推荐

