一.LiveData(攻受)
1.liveData的介绍
LiveData 具有生命周期感知能力,遵循 activity 和 fragment 等实体的生命周期。您可以使用 LiveData 在这些生命周期所有者和生命周期不同的其他对象(例如 ViewModel 对象)之间传递数据。ViewModel 的主要责任是加载和管理与界面相关的数据,因此非常适合作为用于保留 LiveData 对象的备选方法。您可以在 ViewModel 中创建 LiveData 对象,然后使用这些对象向界面层公开状态。这个是官网的解释,在我个人理解看来,livedata主要的作用:
一.借助了lifecycle,解决了观察者的内存泄漏问题;
二.就算不用databinding也能使单向依赖(数据驱动UI)称为可能。
2.liveData的使用
1.UI可见时更新
我们看LiveData的源码,它是个抽象类,我们用它的实现类MutableLiveData来设置数据,同时LiveData也提供了一些方法来监听数据变化。
public abstract class LiveData<T>{
}
public class MutableLiveData<T> extends LiveData<T> {
/**
* Creates a MutableLiveData initialized with the given {@code value}.
*
* @param value initial value
*/
public MutableLiveData(T value) {
super(value);
}
/**
* Creates a MutableLiveData with no value assigned to it.
*/
public MutableLiveData() {
super();
}
/*
*会切换到主线程
*/
@Override
public void postValue(T value) {
super.postValue(value);
}
/*
* 不会切换到主线程,子线程中设置会直接报错
*/
@Override
public void setValue(T value) {
super.setValue(value);
}
}
测试使用
//1.观察生命周期的livedata
info.observe(this){
println("observer $it")
vb.textView.text=it
}
2.可控的观察者
liveData还给我们提供了observeForever()方法,这个方法可以让我们就算应用UI不可见,都会更新ui,不过这个移除需要我们手动调用remove来移除观察者。
//2.需要手动移除
info.observeForever {
println("observerForever:$it")
vb.textView.text=it
}
3.共享数据
liveData还可以共享数据,那它怎么做呢,就是继承自liveData做成一个单例就可以了
class SharePlayState private constructor():LiveData<PlayPresent.PlayerState>() {
override fun postValue(value: PlayPresent.PlayerState?) {
super.postValue(value)
}
companion object{
val instance by lazy {
SharePlayState()
}
}
}
4.原理解析
1.添加观察者
包裹了一层观察者,不可见时会移除观察者,状态改变时通知观察者改变
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//1.感知Activity生命周期状态
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
final @NonNull LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//3.判断Acivity是否存活
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
Lifecycle.@NonNull Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
//2.移除观察者
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
//3.状态改变时通知改变
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
//4.如果存活,发送事件
dispatchingValue(this);
}
}
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
//5.再次检测后发送事件
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//6.如果版本不一致,会发送不出去,这里会决定粘性数据 如果先发送,这个mVersion就会++
//默认的观察者的vesion为-1,这就导致了粘性事件
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
5.粘性事件修改
LiveData 有一个全局的 mVersion ,每次调用 setValue 或 postValue 更新数据时, mVersion 就会加 1,标志着数据版本改变;而新建的 Observer 的 mLastVersion 初始值为 -1。在注册 Observer 时,会触发 LifecycleBoundObserver 状态改变,将 ON_CREATE 、 ON_START 、 ON_RESUME 三种状态分发给 Observer 。此时会判断如果 mLastVersion < mVersion (即数据更新过),就会回调 onChange() 方法通知 Observer 。例如,在 A 页面调用 setValue() 后 mVersion 增加,之后打开 B 页面订阅该 LiveData ,由于 B 页面刚订阅时 mLastVersion 为 -1,与 LiveData 的 mVersion 不一致,当 B 页面生命周期方法执行,满足页面从不可见变为可见、数据版本不一致等条件,就会进行通知,使得 B 页面能接收到 A 页面之前发布的消息。
object LiveDataBus {
//存放订阅者
val bus: MutableMap<String, BusMutableLiveData<Any>> by lazy {
HashMap()
}
//暴漏给外界注册
@Synchronized //同步锁 相当于java的synchronized
fun <T> with(
key: String, type: Class<T>,
isStick: Boolean = true,
): BusMutableLiveData<T> {
if (!bus.containsKey(key)) {
bus[key] = BusMutableLiveData(isStick)
}
return bus[key] as BusMutableLiveData<T>
}
class BusMutableLiveData<T> private constructor() : MutableLiveData<T>() {
var isStick: Boolean = false
//此构造函数
constructor(isStick: Boolean) : this() {
this.isStick = isStick
}
//hook系统源码
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, observer)
if (isStick) {
hook(observer)
} else {
}
}
private fun hook(observer: Observer<in T>) {
//1.获取到LivData的类中的mObservers对象
val liveDataClass: Class<LiveData<*>> = LiveData::class.java
val mObserversField: Field = liveDataClass.getDeclaredField("mObservers")
mObserversField.isAccessible = true//私有修饰也可以访问
//获取到这个成员变量的对象Any==Object
val mObserversObject: Any = mObserversField.get(this)
//得到map对象的class对象 private SafeIterableMap < Observer <? super T>, ObserverWrapper>
val mObserversClass: Class<*> = mObserversObject.javaClass
// 获取到mObservers对象的get方法 protected Entry<K, V> get(K k){
val get: Method = mObserversClass.getDeclaredMethod("get", Any::class.java)
get.isAccessible = true //私有修饰也可以访问
//执行get方法
val invokeEntry: Any = get.invoke(mObserversObject, observer)
//取到entry中的value
var observerWrapper: Any? = null
if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
observerWrapper = invokeEntry.value
}
if (observerWrapper == null) {
throw NullPointerException("observerWrapper is null")
}
//得到observerWrapper的类对象
val supperClass: Class<*> = observerWrapper.javaClass.superclass
val mLastVersion: Field = supperClass.getDeclaredField("mLastVersion")
mLastVersion.isAccessible = true
// 得到mVersion
val mVersion: Field = liveDataClass.getDeclaredField("mVersion")
mVersion.isAccessible = true
val mVersionValue: Any = mVersion.get(this)
mLastVersion.set(observerWrapper, mVersionValue)
}
}
}
二.ViewModel
1.ViewModel简单介绍
ViewModel属于lifecycle(生命周期感知型组件)中的一员,它们是MVVM架构的重要成员。ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据。
2.ViewModel的使用
新建一个继承自ViewModel类,然后在view层(Activity或Fragment)中通过ViewModelProvider(this).get(xxx.class)就可以拿到viewModel的实例。
class PlayViewModel :ViewModel() {
...
val playerStateLiveData = MutableLiveData<PlayPresent.PlayerState>()
...
}
class PlayActivity : AppCompatActivity(){
...
val viewModel=ViewModelProvider(this).get(PlayViewModel::class.java)
...
}
3.ViewModel的创建过程和生命周期关联
我们分两步来看ViewModelProvider(this).get(PlayViewModel::class.java)这个方法,先看ViewModelProvider(),这个方法传的是viewmodelowner,我们可以看到传的是this,然后拿到viewModelProvider这个对象,所以我们的Activity是实现了这个接口的,并生成了ViewModelStore对象,viewModelProvider构造方法中,我们传入this(也就是viewModelOwner),然后ViewModelPovider通过owner.getViewModelStore拿到存储viewModel的ViewModelStore类,并且生成ViewModel的创建工厂。
public interface ViewModelStoreOwner {
/**
* Returns owned {@link ViewModelStore}
*
* @return a {@code ViewModelStore}
*/
@NonNull
ViewModelStore getViewModelStore();
}
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller{
//创建存储viewModel的mViewModelStore
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.");
}
ensureViewModelStore();
return mViewModelStore;
}
}
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
public class ViewModelProvider {
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
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);
}
/**
* Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or
* an activity), associated with this {@code ViewModelProvider}.
* <p>
* The created ViewModel is associated with the given scope and will be retained
* as long as the scope is alive (e.g. if it is an activity, until it is
* finished or process is killed).
*
* @param key The key to use to identify the ViewModel.
* @param modelClass The class of the ViewModel to create an instance of it if it is not
* present.
* @param <T> The type parameter for the ViewModel.
* @return A ViewModel that is an instance of the given type {@code T}.
*/
@SuppressWarnings("unchecked")
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
public static class NewInstanceFactory implements Factory {
private static NewInstanceFactory sInstance;
/**
* Retrieve a singleton instance of NewInstanceFactory.
*
* @return A valid {@link NewInstanceFactory}
*/
@NonNull
static NewInstanceFactory getInstance() {
if (sInstance == null) {
sInstance = new NewInstanceFactory();
}
return sInstance;
}
@SuppressWarnings("ClassNewInstance")
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
}
}
拿到这个viewModelProvider对象后就调用了get()方法,这个方法会先拿到owner.getViewModelStore()中的viewModelstore中拿viewModel,如果拿不到就会通过工厂方法去创建一个viewmodel,并重新创建。这样就完成了viewModel的创建和缓存,那它是怎么感知生命周期的呢?答案就在ComponentActivity中,它的构造方法中,通过和lifeCyle结合,通过观察当前view的生命周期,如果当前event为destroy且不是配置改变(如方向改变)就不会将当前的viewModel从缓存中移除。所以你正常切换横竖屏,他的数据依旧是保存在viewModel中的。
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
4.同一个Activity中多Fragment如何数据共享和通讯
我们从上面的viewModel的创建过程就可以和生命周期就可以得到结论,viewModel的只有在Activity完全销毁时才会被清除,并且它的创建是通过要传入owner和class,如果我们在Fragmen中传入和Activity同一个owner,就可以得到同一个viewModel,这样就可以完成数据共享和通讯了。