请求通俗讲解ViewModel、ViewModel Factory、Repository及LiveData的用法
1. 什么是ViewModel
把Activity/Fragment看作前台店员,负责处理用户交互、渲染界面;ViewModel就是后台仓库管理员,专门管数据存储和业务逻辑。
店员可能因换班、临时离岗(比如屏幕旋转导致Activity重建)消失,但仓库管理员一直在岗,存的数据不会丢。你不用把数据存在店员手里(Activity成员变量),既避免店员离岗时数据丢失,还能防止内存泄漏(Activity销毁时ViewModel不会跟着被销毁,直到真正不需要它的时候)。
使用方法:
- 写一个类继承
ViewModel,在里面定义需要存的数据和处理逻辑:
class UserViewModel : ViewModel() { // 存放用户数据的容器(后面会讲LiveData) val userInfo = MutableLiveData<User>() }
- 在Activity/Fragment里通过
ViewModelProvider获取ViewModel实例:
val viewModel = ViewModelProvider(this)[UserViewModel::class.java]
之后不管Activity重建多少次,拿到的都是同一个ViewModel实例,数据不会丢失。
2. 什么是ViewModel Factory
ViewModel默认只能用无参构造方法创建,但如果你的ViewModel需要参数(比如要传用户ID去加载对应数据),ViewModelProvider没法直接帮你创建带参的实例——这时候ViewModel Factory就是定制ViewModel的工厂,帮你把参数传给ViewModel的构造方法。
使用方法:
- 写一个类实现
ViewModelProvider.Factory,在create方法里创建带参的ViewModel:
class UserViewModelFactory(private val userId: String) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { // 把userId传给ViewModel的构造方法 return UserViewModel(userId) as T } }
- 在Activity里用Factory创建ViewModel:
val viewModel = ViewModelProvider(this, UserViewModelFactory("1001"))[UserViewModel::class.java]
这样就能灵活创建带依赖的ViewModel,不用硬编码参数,也符合解耦的思想。
3. 什么是Repository
Repository是数据中间商,把本地数据库、网络接口、SharedPreferences这些不同的数据源整合到一起。ViewModel不用关心数据是从网络拉的、本地读的还是缓存来的,直接问Repository要就行。
比如ViewModel需要用户数据,Repository会先查本地数据库有没有,没有就去网络请求,拿到数据后存到本地,再返回给ViewModel——ViewModel只需要调用Repository的方法,不用写一堆网络请求、数据库操作的代码。
使用方法:
- 写一个Repository类,封装所有数据源的操作:
class UserRepository(private val userApi: UserApi, private val userDb: UserDatabase) { suspend fun getUser(userId: String): User { // 先查本地数据库 var user = userDb.userDao().getUserById(userId) if (user == null) { // 本地没有就请求网络 user = userApi.fetchUser(userId) // 把数据存到本地 userDb.userDao().insertUser(user) } return user } }
- 在ViewModel里注入Repository(通过Factory传参),调用它的方法获取数据:
class UserViewModel(private val repository: UserRepository) : ViewModel() { fun loadUser(userId: String) { viewModelScope.launch { val user = repository.getUser(userId) userInfo.value = user } } }
这样做的好处是解耦数据层和UI层,多个ViewModel需要同一数据时,不用重复写代码,还能轻松切换数据源(比如测试时把网络换成模拟数据,只改Repository就行)。
4. 什么是LiveData
LiveData是带生命周期感知的可观察数据容器,简单说就是:它装着数据,当数据变化时会自动通知UI更新;而且它只给处于活跃状态的Activity/Fragment发通知(比如Activity在后台时不会收到通知),避免内存泄漏和空指针问题。
比如ViewModel里用LiveData存用户数据,Activity观察这个LiveData,一旦数据变了,UI就自动刷新,不用你手动去监听数据变化再调用UI更新方法。
使用方法:
- 在ViewModel里定义LiveData(通常用
MutableLiveData,内部可以修改数据,对外暴露不可修改的LiveData):
class UserViewModel : ViewModel() { // 内部可修改的MutableLiveData private val _userInfo = MutableLiveData<User>() // 对外暴露不可修改的LiveData,防止外部随意修改数据 val userInfo: LiveData<User> = _userInfo fun updateUser(newUser: User) { // 修改数据,自动通知观察者 _userInfo.value = newUser } }
- 在Activity里观察LiveData,数据变化时更新UI:
viewModel.userInfo.observe(this) { user -> // 自动更新UI userNameTv.text = user.name userAgeTv.text = user.age.toString() }
这样就实现了数据驱动UI,UI和数据自动同步,不用手动管理数据变化的监听逻辑。
内容的提问来源于stack exchange,提问作者Jayanta Sarkar

