1.定义
viewmodel用来存储数据,它是生命周期感知的
2.作用
viewmodel用来将数据从activity中分离出来。viewmodel能够保证当旋转屏幕时activity触发重建,viewmodel里面的数据保持不变
通常将livedata存放在viewmodel中使用
3.实现原理
系统提供ViewModelProvider类用来获取viewmodel对象,ViewModelProvider的初始化方法需要传入activity对象,activity中会保存一个ViewModelStore对象,viewmodel保存在ViewModelStore对象的集合中
ComponentActivity构造函数中会创建LifecycleEventObserver对象来观察activity的生命周期状态,当activity由于屏幕旋转触发销毁时系统不会执行ViewModelStore的clear方法,从而实现activity转屏重建时仍然能够保留viewmodel的功能
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application = checkApplication(activity);
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
转屏时activity会被重新创建,这时从rc中获取转屏之前activity中的viewModelStore对象,从而使新创建的activity和之前activity中的viewModelStore对象建立对应关系
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
//转屏时activity会重新创建,这时从rc中获取转屏之前activity中的viewModelStore对象
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
当转屏重建activity时不会执行clear方法清理ViewModelStore对象中的viewmodel集合,从而使得ViewModelStore中的viewmodel得以保留
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
//当旋转屏幕时不会执行clear方法清理ViewModelStore对象中的viewmodel集合
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
4. 生命周期
viewmodel的生命周期取决于初始化viewmodel时传入的activity生命周期,viewmodel会一直保存在内存中直到activity被销毁,这时系统调用ViewModelStore对象中clear方法清理当前activity下面的所有viewmodel对象
当转屏重建activity时,系统不会清理掉activity下面的viewmodel对象
注意:viewmodel必须不能引用activity对象!如果viewmodel引用activity对象会造成activity在转屏重建后不能被垃圾回收,导致内存泄露
5.实例
-
Activity中获取viewmodel
class MyViewModel : ViewModel() {
private val users: MutableLiveData> by lazy {
MutableLiveData>().also {
it.value = loadUsers()
}
}
fun getUsers(): LiveData> {
return users
}
private fun loadUsers() : List{
return listOf(User("name1"), User("name2"))
}
}
多次调用ViewModelProviders.of方法将获取同一个ViewModel对象
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
val model = ViewModelProviders.of(this)[MyViewModel::class.java]
model.getUsers().observe(this, Observer>{ users ->
// update UI
})
}
}
-
fragment之间共享viewmodel对象
class SharedViewModel : ViewModel() {
val selected = MutableLiveData- ()
fun select(item: Item) {
selected.value = item
}
}
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")
itemSelector.setOnClickListener { item ->
// Update the UI
model.select(item)
}
}
}
class DetailFragment : Fragment() {
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer
- { item ->
// Update the UI
println(item)
})
}
}
activity不需要负责在多个fragment之间传递数据,每个fragment获取同一个viewmodel对象,多个fragment之间不需要相互引用
原文链接:https://github.com/rczh/JetpackGuide