在 Kotlin 中,ViewModel 的获取

在 Kotlin 中,by viewModels()by viewModels { } 都是用来在 Activity 或 Fragment 中获取 ViewModel 实例的属性委托。它们之间的区别在于是否传递自定义的 ViewModelProvider.Factory:

  • by viewModels() 使用默认的 ViewModelProvider.Factory,通常,这个默认工厂会使用 ViewModel 的无参构造函数来创建 ViewModel 实例。
    • 如果 ViewModel 没有参数,或者使用了依赖注入(如 Hilt)来提供 ViewModel,可以使用这种形式;
  • by viewModels {...} 花括号内是一个 Lambda,用于提供自定义的 ViewModelProvider.Factory。当 ViewModel 需要参数时使用,必须提供自定义的 Factory 来创建 ViewModel 实例;

使用指南:

  • 如果 ViewModel 不需要外部参数:使用 by viewModel()
  • 如果 ViewModel 需要参数或依赖:使用 by viewModels { customFactory }
  • 如果使用 Hilt/Dagger 等 DI 框架:使用 by viewModels()(框架自动处理);

添加依赖:

kotlin 复制代码
dependencies {
    // 必需:ViewModel 核心
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
    
    // 必需:Activity 或 Fragment 的委托支持(二选一或都选)
    implementation "androidx.activity:activity-ktx:1.8.2"        // Activity 中使用
    implementation "androidx.fragment:fragment-ktx:1.6.2"       // Fragment 中使用
}

例如:假设我们有一个需要参数的 ViewModel:

kotlin 复制代码
class MyViewModel(private val repository: MyRepository) : ViewModel() {
    // ...
}

那么,在 Activity 或 Fragment 中,我们需要提供一个 Factory 来创建 MyViewModel:

kotlin 复制代码
private val viewModel: MyViewModel by viewModels {
    object : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            // 假设我们已经有了MyRepository的实例
            return MyViewModel(myRepository) as T
        }
    }
}

或者,你可以定义一个 ViewModelFactory 类:

kotlin 复制代码
class MyViewModelFactory(private val repository: MyRepository) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return MyViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

然后,在委托属性中使用:

kotlin 复制代码
private val viewModel: MyViewModel by viewModels {
    MyViewModelFactory(myRepository)
}
相关推荐
ylscode8 分钟前
黑客利用 GHOSTYNETWORKS 和 OMEGATECH 托管 JS 恶意软件基础设施
开发语言·安全·php·安全威胁分析
爱吃生蚝的于勒8 分钟前
QT开发第二章——信号和槽
c语言·开发语言·c++·qt
xcLeigh13 分钟前
Python入门:Python3 operator模块全面学习教程
开发语言·python·学习·教程·python3·operator
大叔带刺15 分钟前
使用python创建自己的专属星座签名APP:Name2Constell
开发语言·python·pygame
z落落17 分钟前
C# 类与对象、字段、静态与非静态+四大访问修饰符
开发语言·c#
思麟呀21 分钟前
C++工业级日志项目(八)最终上层接口
开发语言·c++
石山代码27 分钟前
如何在 C++ 中实现多态?
开发语言·c++
阿方.91828 分钟前
C++ std::function 超全精讲 | 原理语法、适配对象、递归实现、回调场景、面试考点、易错坑点
开发语言·c++·bind·function
weixin_4684668531 分钟前
Markitdown 文档解析快速入门指南
开发语言·python·自动化·编程
我命由我1234533 分钟前
SEO 与 GEO 极简理解
java·linux·运维·开发语言·学习·算法·运维开发