添加依赖
def lifecycle_version = "2.4.0-alpha03"
def arch_version = "2.1.0"
// ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
// Lifecycles only (without ViewModel or LiveData)
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version")
// Saved state module for ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")
// Annotation processor
kapt("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
// optional - helpers for implementing LifecycleOwner in a Service
implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version")
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")
// optional - ReactiveStreams support for LiveData
implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version")
// optional - Test helpers for LiveData
testImplementation("androidx.arch.core:core-testing:$arch_version")
另外添加ViewModel
的扩展
implementation "androidx.activity:activity:1.3.0"
implementation "androidx.activity:activity-ktx:1.3.0"
implementation "androidx.fragment:fragment:1.3.3"
implementation 'androidx.fragment:fragment-ktx:1.3.3'
如果需要在Activity
或者Fragment
中使用ViewModel
,可以直接这样写
val model : XXXViewModel by viewModels()
ViewModel
ViewModel
的职责是为Activity
或者Fragment
管理数据.
如何获取一个ViewModel?
继承
ViewModel
或者AndroidViewModel
class MyViewModel : ViewModel(){ } //如果你需要在ViewModel中使用上下文对象,可以继承AndroidViewModel class MyViewModel2(var application : Application) : AndroidViewModel(){ }
如果继承
AndroidViewModel
,构造函数必须有一个Application
类型的参数,并且只能是Application
,而不是其子类.在
Activity
或者Fragment
中获取MyViewModel
实例对象val myViewModel = ViewModelProviders.of(activity/fragment).get(MyViewModel::class.java)
上面初始化ViewModel
的方式已经过时了。采用如下方式:
val model : XXXViewModel by viewModels()
ViewModel的唯一性
如果一个Activity/Fragment未被销毁,那么多次获取ViewModel,得到的是同一个实例对象.
从源码中去分析这个逻辑.
先看ViewModelPoviders.of()这个方法,返回一个ViewModelProvider对象
public static ViewModelProvider of(@NonNull Fragment fragment) {
return of(fragment, null);
}
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
return of(activity, null);
}
这里只看Activity的
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(ViewModelStores.of(activity), factory);
}
看一下ViewModelProvider这个构造函数
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
this.mViewModelStore = store;
}
当获取到ViewModelProvider对象后,调用其get方法获取到MyViewModel的实例对象
看一下get方法
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//从ViewModelStore中获取ViewModel对象
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
从这里可以看到是从ViewModelStore中获取ViewModel对象.在ViewModelStore中封装了一个HashMap对象.如果HashMap对象中存储了ViewModel对象,就直接复用,如果ViewModel对象未创建,就重新创建后存储在HashMap中.
要保证ViewModel是唯一的,ViewModelStore就必须是唯一的.看一下ViewModelStore是如果获取到的.
在给ViewModelProvider传参数时调用了ViewModelStores.of(activity),看一下这一步做了什么?
//ViewModelStores.java
public static ViewModelStore of(@NonNull FragmentActivity activity) {
if (activity instanceof ViewModelStoreOwner) {
return ((ViewModelStoreOwner) activity).getViewModelStore();
}
return holderFragmentFor(activity).getViewModelStore();
}
查看安卓源码发现,support包下的Fragment和FragmentActivity都继承了ViewModelStoreOwner,自然要实现其方法.
//FragmentActivity
public ViewModelStore getViewModelStore() {
if (this.getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
} else {
if (this.mViewModelStore == null) {
FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
if (nc != null) {
this.mViewModelStore = nc.viewModelStore;
}
if (this.mViewModelStore == null) {
this.mViewModelStore = new ViewModelStore();
}
}
return this.mViewModelStore;
}
}
可以看出,对于一个未销毁的Activity或者Fragment,其ViewModelStore对象是唯一的.那么其存储的ViewModel对象也是唯一的.
ViewModel的特点
由上面可知,Activity或者Fragment未被销毁,ViewModel是唯一的,那么其保存的数据也是不变的,当Activity发生了屏幕旋转等变化时,仍旧可以复用ViewModel中的数据.
不要持有View层的引用
ViewModel内部不要持有View
层的引用,比如Activity
或者Fragment
.可以和LiveData
结合使用
生命周期
由图可看出,Activity重建前后,ViewModel保持不变.
LiveData
LiveData
持有数据,并具有生命周期感知能力,即遵循其他组件(如Activity,Fragment和Service)的生命周期。这种感知能力可确保 LiveData
仅更新处于活跃生命周期状态的应用组件观察者。应用组件观察者处于STARTED
或者RESUMED
状态时,我们认为该观察者处于活跃状态。
继承关系如下:
[LiveData] <- [MutableLiveData] <- [MediatorLiveData] MutableLiveData
对外暴露setValue
和postValue
.MediatorLiveData
观察别的LiveData
.并能将active/inactive
状态传递给它所观察的LiveData
对象.
postValue与setValue
postValue
可以从后台线程更新数据,setValue
只能在主线程中更新数据.如果同时调用这两个方法,postValue
设置的数据会覆盖code>setValue设置的数据.postValue
是通过ArchTaskExecutor
来实现在主线程中更新数据.在ArchTaskExecutor
中使用主线程的Handler
.
粘性问题
observeForever与removeObserver
如果一个观察者通过observeForever
被添加,这个观察者会被认为一直处于激活状态,任何数据更新都会立即通知到它.因此需要手动调用removeObserver
去移除它.
onActive与onInactive
onActivity
:有观察者处于活跃状态。onInactive
: 没有处于活跃状态的观察者,并不是没有观察者。
Lifecycle 与 LifecycleOwner
v4包下的SupportActivity
和Fragment
默认都实现了LifecycleOwner(API27)
,并且都默认初始化了LifeCycle
实例。
//LifecycleOwner
public interface LifecycleOwner {
/**
* Returns the Lifecycle of the provider.
*
* @return The lifecycle of the provider.
*/
@NonNull
Lifecycle getLifecycle();
}
//supportActivity
public class SupportActivity extends Activity implements LifecycleOwner, Component {
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
public Lifecycle getLifecycle() {
return this.mLifecycleRegistry;
}
}
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
ViewModelStoreOwner {
LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
}
public class LifecycleRegistry extends Lifecycle {
//.........
}
Event
Event#ON_CREATE
,Event#ON_START
和Event#ON_RESUME
在LifecycleOwner
对应的生命周期回调之后执行。Event#ON_PAUSE
,Event#ON_STOP
和Event#ON_DESTROY
在LifecycleOwner
对应的生命周期回调之前执行。
State
State
作为节点,而Event
则在节点间流动。典型的状态机模式。
ProcessLifecycleOwner
ViewTreeLifecycleOwner
LifecycleObserver
如果你使用的是java8,可以通过添加以下依赖来使用DefaultLifecycleObserver
android.arch.lifecycle:common-java8:<version>
然后实现DefaultLifecycleObserver
。如果同时使用了注解OnLifecycleEvent
,注解会被忽略。DefaultLifecycleObserver
优先于注解。参考这里
class TestObserver implements DefaultLifecycleObserver {
@Override
public void onCreate(LifecycleOwner owner) {
// your code
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreateX(LifecycleOwner owner){
}
}
如果使用的是java7,通过注解来监听生命周期事件.并且可以给对应的生命周期方法添加一个LifecycleOwner
参数.如果方法被Lifecycle.Event.ON_ANY
注解,那么该方法可以额外添加一个Lifecycle.Event.ON_ANY
参数.
class TestObserver implements LifecycleObserver {
@OnLifecycleEvent(ON_CREATE)
void onCreated(LifecycleOwner source) {}
@OnLifecycleEvent(ON_ANY)
void onAny(LifecycleOwner source, Event event) {}
}
google官方MVVM架构图
由图可以看出,不管数据从哪里来,最终要汇聚到数据仓库,LiveData
观察的是数据仓库的变化.并且ViewModel
中可以定义多个LiveData
.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。