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

Android多模块项目如何跨模块实现Shared ViewModel数据共享

多模块架构下跨Fragment共享Activity级ViewModel的实现方案

问题根因

默认ViewModel实例不匹配的核心原因是ViewModel的存储规则:

  • ViewModel存储在宿主Activity的ViewModelStore中时,默认Key由传入的获取类的全限定名生成,格式为androidx.lifecycle.ViewModelProvider.DefaultKey:{类全路径名}
  • 调用activityViewModels<CoreViewModel>()时,系统会匹配Key对应CoreViewModel的实例,找不到就通过默认工厂反射新建CoreViewModel实例存入,自然和之前存储的MainViewModel不是同一个对象。

可行实现方案(无模块耦合)

核心思路是依赖倒置+统一存储Key,子模块只依赖公共层定义的抽象契约,完全不需要感知app层的MainViewModel具体实现,不会破坏模块分层。

步骤1:在公共core模块定义共享契约

所有业务模块、app模块都依赖core模块,在这里定义跨模块共享的ViewModel抽象,不要用通用的CoreViewModel作为共享类型:

// core模块内定义,所有子模块都能引用
abstract class SharedActivityViewModel : ViewModel() {
    // 仅定义跨模块需要访问的字段、方法
    abstract val loginState: LiveData<Boolean>
    abstract fun updateLoginState(isLogin: Boolean)
}

如果需要更细的边界控制,也可以用interface代替抽象类。

步骤2:app层MainViewModel实现契约

// app模块内的MainViewModel,子模块完全不需要引用这个类
class MainViewModel : SharedActivityViewModel() {
    override val loginState = MutableLiveData<Boolean>()
    override fun updateLoginState(isLogin: Boolean) {
        loginState.value = isLogin
    }

    // 这里可以写MainViewModel私有的业务逻辑,不会暴露给子模块
}

步骤3:宿主Activity提前绑定实例

在MainActivity加载Fragment之前,主动将MainViewModel实例以公共契约类为Key存入ViewModelStore:

// app模块MainActivity
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 初始化自身需要的MainViewModel实例
        val mainVm by viewModels<MainViewModel>()
        // 将实例绑定到公共契约类对应的Key上
        ViewModelProvider(this)[SharedActivityViewModel::class.java] = mainVm

        // 后续加载Fragment等正常逻辑
        setContentView(R.layout.activity_main)
        // ...
    }
}

步骤4:子模块Fragment直接获取实例

任意模块下挂载到MainActivity的Fragment,都可以直接通过公共契约类获取同一个共享实例:

// 任意子模块的Fragment,不需要依赖app模块
class MineFragment : Fragment() {
    // 直接拿到的就是MainActivity中的MainViewModel实例
    private val sharedVm by activityViewModels<SharedActivityViewModel>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 直接使用共享数据即可
        sharedVm.loginState.observe(viewLifecycleOwner) { isLogin ->
            // 更新UI
        }
    }
}

注意事项

  • 不要让子模块直接依赖app模块的MainViewModel,会造成循环依赖,彻底破坏分层架构
  • 公共契约中只定义跨模块需要访问的成员,不要把MainViewModel的私有业务逻辑暴露在契约中,做好边界隔离
  • 不建议通过硬编码字符串Key的方式存储ViewModel,类型不安全,容易出现类型转换异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:57:21