如何实现全应用级ViewModel 完成多Fragment与Activity间数据收发
实现全应用共享的ViewModel方案
常规ViewModel默认绑定对应Activity/Fragment的生命周期,页面销毁时会同步回收ViewModel实例。要实现跨多个Activity、Fragment收发数据的全局ViewModel,核心是将ViewModel的存储宿主替换为Application实例,让ViewModel的生命周期和应用的整个生命周期保持一致。
具体实现步骤
- 第一步:自定义实现
ViewModelStoreOwner接口的Application类
Application本身默认没有实现ViewModelStoreOwner接口,需要手动添加全局ViewModel存储逻辑:
class MyApp : Application(), ViewModelStoreOwner { // 全局ViewModel存储实例,应用存活期间不会被销毁 private val appViewModelStore = ViewModelStore() override fun getViewModelStore(): ViewModelStore { return appViewModelStore } }
写完后需要在AndroidManifest.xml的application标签中配置自定义的Application:
<application android:name=".MyApp" ...其他配置> ...四大组件配置 </application>
- 第二步:创建自定义的全局共享ViewModel
可以根据需求选择LiveData或者Flow来实现数据的收发:
class SharedAppViewModel : ViewModel() { // 示例:用SharedFlow实现事件发送,replay=1代表粘性事件,不需要粘性可以设为0 private val _globalEvent = MutableSharedFlow<String>(replay = 1) val globalEvent: SharedFlow<String> = _globalEvent fun sendGlobalEvent(content: String) { viewModelScope.launch { _globalEvent.emit(content) } } // 也可以用LiveData实现 // private val _globalLiveData = MutableLiveData<String>() // val globalLiveData: LiveData<String> = _globalLiveData // fun sendLiveDataEvent(content: String) { // _globalLiveData.postValue(content) // } }
- 第三步:在任意Activity/Fragment中获取并使用ViewModel
获取时将ViewModelProvider的宿主指定为我们自定义的Application实例即可,所有位置拿到的都是同一个ViewModel实例:
// 任意Activity/Fragment中都可以这样获取 val sharedViewModel = ViewModelProvider(applicationContext as MyApp)[SharedAppViewModel::class.java] // 发送数据示例 sharedViewModel.sendGlobalEvent("测试跨页面消息") // 订阅接收数据示例 lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { sharedViewModel.globalEvent.collect { eventContent -> // 此处处理收到的消息 } } }
注意事项
- 禁止在全局ViewModel中持有任何Activity、Fragment、View的上下文引用,避免出现内存泄漏,需要使用上下文时仅使用Application上下文
- 不需要的粘性事件要及时清理,避免出现预期外的重复回调
- Java项目实现逻辑完全一致,仅需要将上述Kotlin代码转换为对应Java语法即可
- 如果没有协程管理、ViewModel架构适配的需求,也可以用单例类配合LiveData/Flow实现相同的跨页面通信效果
内容的提问来源于stack exchange,提问作者adnan salem
相关产品推荐
相关产品推荐

