Android LiveData:如何在不同Activity中复用同一个ViewModel?
在Android不同Activity中复用同一个ViewModel的实现方案
默认情况下,我们用ViewModelProviders.of(this)(或新版ViewModelProvider(this))获取ViewModel时,每个Activity都会拿到独立的实例——因为每个Activity都有自己的ViewModelStore,ViewModel会和宿主的生命周期绑定。要在多个Activity间复用同一个ViewModel,核心思路是让它们共享同一个ViewModelStoreOwner,下面给两种实用的实现方式:
方法一:以Application作为ViewModelStoreOwner(官方推荐)
Application是全局唯一的组件,它的生命周期和整个应用一致,用它作为ViewModel的宿主,所有Activity通过它获取的ViewModel都会是同一个实例。
步骤示例
- 你的
NameViewModel代码保持不变:
public class NameViewModel extends ViewModel { private MutableLiveData<String> mCurrentName; public MutableLiveData<String> getCurrentName() { if (mCurrentName == null) { mCurrentName = new MutableLiveData<>(); } return mCurrentName; } }
- 主Activity中获取ViewModel并观察:
// 关键:把this换成getApplication(),用Application作为宿主 NameViewModel mModel = new ViewModelProvider(getApplication()).get(NameViewModel.class); // 创建UI观察者 final Observer<String> nameObserver = textView::setText; // 观察LiveData,Activity销毁时会自动移除观察者 mModel.getCurrentName().observe(this, nameObserver); // 示例:点击按钮更新LiveData值 updateBtn.setOnClickListener(v -> { mModel.getCurrentName().setValue("来自主Activity的新名字"); });
- 第二个Activity中复用同一个ViewModel:
// 同样用getApplication()获取ViewModel实例 NameViewModel sharedModel = new ViewModelProvider(getApplication()).get(NameViewModel.class); // 观察LiveData,当主Activity更新值时,这里的UI会同步刷新 sharedModel.getCurrentName().observe(this, newName -> { secondActivityTextView.setText(newName); });
这种方式不需要额外写单例代码,符合Jetpack的设计规范,是最省心的方案。
方法二:自定义单例ViewModelStoreOwner(适用于特定页面组共享)
如果你只想在某几个特定Activity间共享ViewModel,且希望这些页面全部销毁后自动清理ViewModel(避免和应用生命周期绑定导致的内存占用),可以自定义一个单例的ViewModelStoreOwner:
步骤示例
- 实现单例的ViewModelStoreOwner:
public class SharedViewModelStoreOwner implements ViewModelStoreOwner { // 单例实例 private static final SharedViewModelStoreOwner INSTANCE = new SharedViewModelStoreOwner(); private final ViewModelStore viewModelStore = new ViewModelStore(); // 私有构造方法防止实例化 private SharedViewModelStoreOwner() {} public static SharedViewModelStoreOwner getInstance() { return INSTANCE; } @NonNull @Override public ViewModelStore getViewModelStore() { return viewModelStore; } // 手动清理方法:在最后一个共享Activity销毁时调用,避免内存泄漏 public void clearViewModelStore() { viewModelStore.clear(); } }
- 在Activity中获取ViewModel:
// 用自定义的单例Owner获取ViewModel NameViewModel mModel = new ViewModelProvider(SharedViewModelStoreOwner.getInstance()).get(NameViewModel.class); // 后续的观察、更新逻辑和方法一一致
- 记得在合适的时机清理:比如在最后一个共享Activity的
onDestroy()中调用SharedViewModelStoreOwner.getInstance().clearViewModelStore();
注意事项
- 用Application作为宿主时,ViewModel的生命周期和应用一致,如果ViewModel持有大对象或资源,要注意在不需要时手动清理数据,避免内存泄漏。
- LiveData的
observe()方法会自动感知Activity的生命周期,当Activity处于销毁状态时,会自动移除观察者,不用担心内存泄漏问题。 - 如果你用Kotlin开发,代码会更简洁,比如
val model = ViewModelProvider(application).get(NameViewModel::class.java)
内容的提问来源于stack exchange,提问作者user1209216
相关产品推荐
相关产品推荐

