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

Jetpack Compose中by viewModels()与viewModel<ViewModel>()的区别及原理问询

Jetpack Compose中两种ViewModel获取方式的区别与原理

两种方式的核心区别

这两种写法的核心功能一致——都是获取与当前Compose作用域(Activity/Fragment或导航栈条目)绑定的ViewModel实例,但在语法和初始化逻辑上有细微差异:

  • 语法形式与初始化时机
    • 方式一(委托属性):val myViewModel: MyViewModel by viewModels()
      借助Kotlin委托属性实现,ViewModel实例会在首次访问该属性时延迟初始化,无需提前创建实例。
    • 方式二(直接调用函数):val myViewModel = viewModel<MyViewModel>()
      直接调用viewModel()函数并通过显式泛型指定类型,ViewModel实例在代码执行到该行时立即初始化。
  • 类型指定方式
    • 方式一通过变量的类型注解推导ViewModel类型;
    • 方式二通过函数的泛型参数明确声明ViewModel类型。

方式一的工作原理

by viewModels()本质是Kotlin委托属性的应用:

  1. viewModels()函数会返回一个实现了ReadOnlyProperty的委托对象;
  2. 当你第一次访问myViewModel时,委托对象会先找到当前Compose对应的ViewModelStoreOwner(比如宿主Activity或导航栈条目);
  3. 通过ViewModelProvider从ViewModelStore中查找是否存在MyViewModel实例:
    • 存在则直接返回已有实例;
    • 不存在则用默认(或自定义)的ViewModelFactory创建新实例,并存入ViewModelStore;
  4. 最终将获取到的ViewModel实例返回给属性调用者。

关于类型注解的疑问

是的,方式一确实依赖变量后的MyViewModel类型注解来确定要初始化的ViewModel。viewModels()是泛型函数,Kotlin会通过类型推导,从属性的类型注解中拿到泛型参数T的具体类型,从而创建对应的ViewModel实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:30:23