jetPack组件必学#LiveData&ViewMode

39 阅读8分钟

jetPack组件必学#Lifecycle

jetPack组件必学#LiveData&ViewMode

jetPack组件必学#DataBinding

jetPack组件必学#Dagger2&Hilt

jetPack组件必学#Navigation

jetPack组件必学#Room

一.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,这样就可以完成数据共享和通讯了。