在 Kotlin 中ViewModel 的获取及使用指南

 更新时间:2025年10月24日 16:54:40   作者:橙子19911016  
在Kotlin中,by viewModels()和by viewModels{ }都是用来在 Activity 或 Fragment 中获取 ViewModel 实例的属性委托,接下来通过本文给大家介绍在Kotlin中ViewModel的获取及使用指南,感兴趣的朋友跟随小编一起看看吧

在 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()(框架自动处理);

添加依赖:

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:

class MyViewModel(private val repository: MyRepository) : ViewModel() {
    // ...
}

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

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 类:

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")
    }
}

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

private val viewModel: MyViewModel by viewModels {
    MyViewModelFactory(myRepository)
}

补充:Kotin- Fragment 获取 ViewModel 实例正确方式

Kotin- Fragment 获取 ViewModel 实例正确方式

1. 第一种获取方式:

通常获取 ViewModel 方法:

 val model : BlankViewModel by lazy{
        ViewModelProvider(this,BlankViewModel.BlankViewModelFactory()).get(BlankViewModel::class.java)
 }
 //该方法已被废弃:viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

对应的 BlankViewModelFactory 方法

class BlankViewModel : ViewModel() {
    // TODO: Implement the ViewModel
    private val number = MutableLiveData<Int>();
    private var i=0
    fun getNumber() : LiveData<Int>{
        return number
    }
    fun addNumber(){
        i++
        number.value = i
    }
    class BlankViewModelFactory(): ViewModelProvider.Factory{
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            return BlankViewModel() as T
        }
    }
}

当我们创建 Fragment 页面,并将页面添加到一个 Activity 页面中时,想要实现在 Activity 中调用 ViewModel 中的方法使得 livedata 的数据改变,并希望 Fragment 页面也可以监听到变化,此时就需要获取到同一个 ViewModel 实例,才能保证两个页面的数据同时变化。

首先,在 Activity 中获取 BlankViewModel ,并通过点击按钮调用其中的 addNumber 方法,让变量+1

class FragmentActivity : AppCompatActivity() {
    val model : BlankViewModel by lazy{
        ViewModelProvider(this,BlankViewModel.BlankViewModelFactory()).get(BlankViewModel::class.java)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_fragment)
        val button = findViewById<Button>(R.id.add).setOnClickListener {
              model.addNumber()
        }
    }
}

第一个 Fragment 页面:

class LeftFragment : Fragment() {
    val model : BlankViewModel by lazy{
        ViewModelProvider(requireActivity(),BlankViewModel.BlankViewModelFactory()).get(BlankViewModel::class.java)
    }
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.blank_fragment, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val left = view.findViewById<TextView>(R.id.left_tv)
        model.getNumber().observe(requireActivity(), Observer {
            Log.d("IT",""+it)
            left.text = it.toString()
        })
    }
}

在获取 ViewModel 实例时,ViewModelProvider 中的第一个参数 ViewModelStoreOwner 对象传递的是requireActivity 方法,这个方法里就是获取当前的 Activity 实例 ;如果该位置仍然传 this ,则获取的是与 Activity 不同的 ViewModel 实例,这样 Activity 点击按钮时 Fragment 页面的数值并不会变化。

val model : BlankViewModel by lazy{     
  ViewModelProvider(requireActivity(),BlankViewModel.BlankViewModelFactory()).get(BlankViewModel::class.java)
}

在观察变化的方法中,也是同样的道理:

  model.getNumber().observe(requireActivity(), Observer {
            left.text = it.toString()
 })

另一个 Fragment 页面和它一样,这里就不添加了。

2. 第二种获取方式

通过ktx简化:
添加 ktx 依赖,这里要注意版本,我的 kotlin 版本过低,下载高版本会报红:

implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation "androidx.activity:activity-ktx:1.0.0-alpha03"

在 Activity 页面中:

//这里省略掉其他部分
val model by viewModels<BlankViewModel>()

在 Fragment 页面中

//这里省略掉其他部分
val model by activityViewModels<BlankViewModel>()
//这里可以正常传this
model.getNumber().observe(this, Observer {
            Log.d("IT",""+it)
            left.text = it.toString()
})

以上就是获取同一 ViewModel 实例的方法。如有不对,请指正。

到此这篇关于在 Kotlin 中ViewModel 的获取及使用指南的文章就介绍到这了,更多相关Kotlin  ViewModel 获取内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android实现滤镜效果ColorMatrix

    Android实现滤镜效果ColorMatrix

    这篇文章主要为大家详细介绍了Android实现滤镜效果ColorMatrix,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • Android 8.0系统中应用图标的适配技巧

    Android 8.0系统中应用图标的适配技巧

    今天小编就为大家分享一篇关于Android 8.0系统中应用图标的适配技巧,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • Android 自定义AlertDialog对话框样式

    Android 自定义AlertDialog对话框样式

    实际的项目开发当中,经常需要根据实际的需求来自定义AlertDialog。最近在开发一个WIFI连接的功能,点击WIFI需要弹出自定义密码输入框,具体代码大家参考下本文
    2017-09-09
  • HorizontalScrollView水平滚动控件使用方法详解

    HorizontalScrollView水平滚动控件使用方法详解

    这篇文章主要为大家详细介绍了HorizontalScrollView水平滚动控件的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • android编程实现类似于支付宝余额快速闪动效果的方法

    android编程实现类似于支付宝余额快速闪动效果的方法

    这篇文章主要介绍了android编程实现类似于支付宝余额快速闪动效果的方法,涉及Android时间函数的相关使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • Android仿微信图片上传带加号且超过最大数隐藏功能

    Android仿微信图片上传带加号且超过最大数隐藏功能

    这篇文章给大家分享android仿照微信空间上传图片,显示图片数量以及超过最大,上传按钮隐藏功能,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2018-03-03
  • 举例讲解Android应用开发中OTTO框架的基本使用

    举例讲解Android应用开发中OTTO框架的基本使用

    这篇文章主要介绍了Android应用开发中OTTO框架的基本使用讲解,文中举了创建一个单例模式的应用例子,需要的朋友可以参考下
    2016-02-02
  • Android学习笔记(二)之电话拨号器

    Android学习笔记(二)之电话拨号器

    目前手机市场上android已经具有强大的霸主地位,吸引了很多的追棒者,android学习越来越火热,本文给大家介绍android学习笔记(二)之电话拨号器,感兴趣的朋友一起学习吧
    2015-11-11
  • Android.mk文件使用速通手册

    Android.mk文件使用速通手册

    本文将简要介绍 Android.mk 的使用,看完本文,你将学会如何将自己的代码通过 Android.mk 来编译到工程中,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Android Studio 3.6 调试 smali的全过程

    Android Studio 3.6 调试 smali的全过程

    这篇文章主要介绍了Android Studio 3.6 调试 smali, 目前最新版的 Android Studio 利用附加功能调试 smali 非常方便,具体操作步骤跟随小编一起看看吧
    2020-02-02

最新评论