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

无Fragment的Activity中二次获取ViewModel的最优方案

Activity中二次获取ViewModel的最佳实践

问题背景

官方推荐在Activity的onCreate方法内通过以下方式首次获取ViewModel:

public class FooActivity extends AppCompatActivity {

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        
        FooViewModel viewModel = new ViewModelProvider(this, viewModelFactory)
            .get(FooViewModel.class);
    }

}

但每次创建ViewModelProvider会有冗余开销,若需要在onCreate之外二次获取ViewModel,该如何处理?常见疑问包括:

  • 将ViewModel缓存到Activity私有变量是否会导致泄漏?
  • 在onDestroy中手动将ViewModel置为null是否更安全?
  • 无Fragment的Activity中,二次获取关联ViewModel的推荐方式是什么?

解答

1. 缓存ViewModel到Activity成员变量不会导致泄漏

你示例中把ViewModel存在Activity私有变量的写法是安全的,不会引发内存泄漏。原因在于:

  • ViewModel的生命周期由ViewModelStore管理,当Activity因配置变化(如旋转)重建时,ViewModel会被保留;当Activity真正销毁(非配置变化场景)时,ViewModelStore会自动调用clear()方法销毁ViewModel,此时Activity对ViewModel的引用也会随之失效。
  • 手动在onDestroy中将ViewModel置为null完全是多余操作,系统已经会妥善处理ViewModel的生命周期,无需额外干预。

2. 二次获取ViewModel的推荐方式

推荐以下两种高效且安全的方案:

方案一:缓存ViewModel到Activity成员变量(最简便)

直接将ViewModel作为Activity的成员变量,在onCreate中初始化后,后续在任意生命周期方法或自定义方法中直接使用即可,无需重复获取:

public class FooActivity extends AppCompatActivity {
    private FooViewModel viewModel;

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        
        viewModel = new ViewModelProvider(this, viewModelFactory)
            .get(FooViewModel.class);
    }

    @Override
    protected void onStop() {
        //...
        
        viewModel.someMethod();
    }

}
方案二:缓存ViewModelProvider实例

如果需要获取多个不同类型的ViewModel,可以缓存ViewModelProvider而非单个ViewModel,后续通过该Provider实例获取对应ViewModel,避免重复创建Provider:

public class FooActivity extends AppCompatActivity {
    private ViewModelProvider viewModelProvider;

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //...
        viewModelProvider = new ViewModelProvider(this, viewModelFactory);
        // 首次获取FooViewModel
        FooViewModel fooViewModel = viewModelProvider.get(FooViewModel.class);
    }

    private void handleSomeAction() {
        // 二次获取FooViewModel
        FooViewModel fooViewModel = viewModelProvider.get(FooViewModel.class);
        // 获取其他类型ViewModel
        BarViewModel barViewModel = viewModelProvider.get(BarViewModel.class);
    }
}

补充说明

即使你不缓存ViewModel或ViewModelProvider,每次通过new ViewModelProvider(this, viewModelFactory).get(...)获取的也是同一个ViewModel实例——因为ViewModelProvider内部会从Activity关联的ViewModelStore中查找已有实例,不存在重复创建ViewModel的问题,只是创建ViewModelProvider本身有微小的开销,所以缓存是更优选择。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:13:13