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

Jetpack Compose中MVVM模式下SurfaceView与ViewModel交互问题

优化方案:用DisposableEffect实现解耦的MVVM架构

你的核心问题在于ViewModel持有视图层的SurfaceView,这既违反了MVVM的职责分离原则(ViewModel不应依赖视图组件),还可能导致内存泄漏(ViewModel生命周期远长于视图)。下面是用DisposableEffect优化的实现,完全符合MVVM规范:

1. 重构ViewModel:剥离视图依赖

ViewModel只负责管理流的可用性状态,以及提供启动/停止流的方法(需要视图层传入SurfaceView,而非持有它):

class CameraVM : ViewModel() {
    // 暴露流是否可用的状态,供视图层监听
    private val _isStreamSourceAvailable = MutableStateFlow(false)
    val isStreamSourceAvailable = _isStreamSourceAvailable.asStateFlow()

    init {
        listenForStreamSourceAvailability()
    }

    private fun listenForStreamSourceAvailability() {
        // 替换为实际的SDK源可用性监听逻辑
        viewModelScope.launch {
            // 模拟源可用的回调
            _isStreamSourceAvailable.value = true
        }
    }

    // 启动流:由视图层传入准备好的SurfaceView
    fun startStreaming(surfaceView: SurfaceView) {
        camera.setupStreaming(surfaceView)
        camera.startStreaming()
    }

    // 可选:根据业务需求实现停止流的逻辑
    fun stopStreaming() {
        camera.stopStreaming()
    }
}

2. 重构Compose视图:用DisposableEffect处理生命周期与状态联动

在CameraView中,用DisposableEffect监听视图组合状态和流源的可用性,满足你要求的两种启动场景,同时避免ViewModel与视图耦合:

@Composable
fun CameraView(viewModel: CameraVM = viewModel()) {
    val context = LocalContext.current
    // 监听流源是否可用的状态
    val isSourceAvailable by viewModel.isStreamSourceAvailable.collectAsState()

    // 用remember缓存SurfaceView,避免重复创建
    val surfaceView = remember { SurfaceView(context) }

    // 渲染SurfaceView
    AndroidView(factory = { surfaceView })

    // 用DisposableEffect处理视图生命周期与状态变化
    DisposableEffect(surfaceView, isSourceAvailable) {
        // 场景1:视图首次组合且源可用;场景2:源变为可用且视图可见
        if (isSourceAvailable) {
            viewModel.startStreaming(surfaceView)
        }

        // 当Compose节点被销毁时执行清理(比如释放Surface资源、停止流)
        onDispose {
            viewModel.stopStreaming()
        }
    }
}

方案优势

  • 严格遵循MVVM:ViewModel不再依赖任何视图层组件,只专注业务状态和逻辑,视图层负责视图渲染和生命周期回调。
  • 满足启动场景:DisposableEffect会在surfaceView或isSourceAvailable发生变化时触发,完美覆盖你要求的两种启动时机。
  • 避免内存泄漏:onDispose回调会在视图销毁时执行清理,确保Surface资源和流的正确释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:25:29