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

多模块Android项目中非持久化长任务跨模块同步进度的方案咨询

解决方案建议

针对你的多模块长任务需求,推荐以下两种适配场景的方案,均符合模块隔离规则且规避已尝试方案的问题:


方案1:共享模块单例协程容器 + Flow 进度传递

利用共享模块的全局可访问性,创建单例类管理长任务与进度分发,直接传递大对象且保证任务在进程存活期间持续运行。

实现步骤

  1. 共享模块中定义任务管理单例
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()
        }
    }
}
  1. Module A 启动任务
    直接调用共享模块的单例方法,无需跨模块传递大对象:
// 在Module A的业务逻辑中
LongTaskManager.instance.startSdkTask(yourLargeObject)
  1. 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规范。

实现步骤

  1. 共享模块中定义应用级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
    }
}
  1. 封装ViewModel获取工具(共享模块)
    避免各模块重复编写获取逻辑:
object ViewModelHelper {
    fun getAppLevelViewModel(activity: Activity): AppLevelTaskViewModel {
        return ViewModelProvider(
            activity.applicationContext as ViewModelStoreOwner,
            ViewModelProvider.AndroidViewModelFactory.getInstance(activity.application)
        )[AppLevelTaskViewModel::class.java]
    }
}
  1. Module A 启动任务
val appViewModel = ViewModelHelper.getAppLevelViewModel(requireActivity())
appViewModel.startSdkTask(yourLargeObject)
  1. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:06:29