Android Jetpack架构组件之 LiveData(使用、源码篇)

1、前言

最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面。

Android Architecture组件是Android Jetpack的一部分,它们是一组库,旨在帮助开发者设计健壮、可测试和可维护的应用程序,包含一下组件:

  •  带你领略Android Jetpack组件的魅力
  • Android Jetpack 架构组件之 Lifecycle(使用篇)
  • Android Jetpack 架构组件之 Lifecycle(源码篇)
  • Android Jetpack 架构组件之 ViewModel (源码篇)
  • Android Jetpack 架构组件之 LiveData(使用、源码篇)
  • Android Jetpack架构组件之 Paging(使用、源码篇)
  • Android Jetpack 架构组件之 Room(使用、源码篇)
  • Android Jetpack 架构组件之Navigation
  • Android Jetpack架构组件之WorkManger
  • 实战:从0搭建Jetpack版的WanAndroid客户端​​​​​​​

上述时Android Architecture所提供的架构组件,本文主要从使用和源码的角度了解一下LiveData组件

2、LiveData简介

  • LiveData是一个具有生命周期感知特性的可观察的数据保持类,使用LiveData保存数据时,在每次订阅或数据更新时会自动回调设置的观察者从而更新数据,真正的实现了数据驱动的效果
  • LiveData的创建基本会在ViewModel中,从而使数据在界面销毁时继续保持
  • LiveData 认为观察者的生命周期处于STARTED状态或RESUMED状态下,表示观察者处于活动状态,LiveData只通知活跃的观察者更新数据
  • 注册一个实现该LifecycleOwner 接口的对象配对的观察者,当相应Lifecycle对象的状态改变为DESTROYED时移除观察者

3、LiveData的使用

  • 创建一个LiveData实例来保存某种类型的数据
class TestViewModel : ViewModel() {
    var mCurrent: MutableLiveData? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
}
  1. 请确保存储LiveData对象是在ViewModel中而不是活动或片段
  • 创建一个定义onChanged()方法的Observer对象,在数据变化时回调
//创建观察者对象
val nameObservable = Observer {   // 创建观察者对象
    textView.text = it       // 定义onChange()方法中的操作
}
  • 使用LifecycleOwner的observe() 方法将观察者对象附加到LiveData对象,这将观察对象向LiveData对象订阅,以便通知其更改
// 如果在View Model中使用,先创建ViewModel的对象
mModel = ViewModelProviders.of(this).get(TestViewModel::class.java)

// mCurrent 订阅观察
mModel.mCurrent!!.observe(this, nameObservable)  
  1. 第一个参数传递的this就是LifecycleOwner 的实例,LiveData会根据Owner的声明周期自动作相应的处理
  2. observe()将nameObservable作参数调用后,如果LiveData数据有值,onChange()立即调用获取最新值
  3. 可以使用observeForever(Observer)方法注册一个没有关联的生命周期所有者对象的观察者,在这种情况下,观察者被认为总是活动的,因此总是通知修改,可以删除这些观察员调用removeObserver(Observer) 方法
  • LiveData允许UI控制器观察员订阅更新
// 设置两个点击事件,修改LiveData中的数据
btnChange.setOnClickListener { mModel.mCurrent!!.value = "AAAAA" }
btnB.setOnClickListener { mModel.mCurrent!!.value = "BBBBB" }
  1. 当LiveData对象保存的数据发生变化时,UI会自动响应更新
  2. 观察者在从非活动状态变为活动状态时也会收到更新
  • 运行结果:点击按钮后改变LiveData的数据,界面的TextView也随之改变

Android Jetpack架构组件之 LiveData(使用、源码篇)_第1张图片

4、转换LiveData

  • Transformations.map():对存储在LiveData对象中的值应用函数,并将结果传播到下游
// 将返回开始示例中的 mCurrent 值的长度
var liveDataMap: LiveData = Transformations.map(mCurrent) { input: String -> input.length }
  • Transformations.switchMap() :第二个参数返回 一个LiveData
var livaDataSwich : LiveData = Transformations.switchMap(mCurrent){
    input: String? ->  MutableLiveData().also { it.value = input!!.toLowerCase() }
}
  • 对上面转换的LiveData订阅观察
val lowObservable = Observer {
    textViewLow.text = it
}
val lengthObservable = Observer {
    textViewLength.text = it.toString()
}

mModel.liveDataMap.observe(this, lengthObservable)
mModel.livaDataSwich.observe(this, lowObservable)

Android Jetpack架构组件之 LiveData(使用、源码篇)_第2张图片

 

  • 使用场景
  1. 将LiveData对象分发给观察者之前对其中存储的值进行更改
  2. 需要LiveData根据另一个实例的值返回其他 实例
  3. 当基础的LiveData改变时,转换后的LiveData也会改变并且触发UI更新

5、扩展LiveData

public class LocationLiveData extends LiveData {
    private static LocationLiveData sInstance;
    private LocationManager locationManager;

    @MainThread
    public static LocationLiveData get(Context context) {
        if (sInstance == null) {
            sInstance = new LocationLiveData(context.getApplicationContext());
        }
        return sInstance;
    }

    private SimpleLocationListener listener = new SimpleLocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            setValue(location);
        }
    };

    private LocationLiveData(Context context) {
        locationManager = (LocationManager) context.getSystemService(
                Context.LOCATION_SERVICE);
    }

    @Override
    protected void onActive() {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
    }

    @Override
    protected void onInactive() {
        locationManager.removeUpdates(listener);
    }
}
  1. onActive() :当LiveData对象具有活动观察者时调用该方法
  2. onInactive() :当LiveData对象没有任何活动观察者时调用该方法
  3. setValue(T) :方法更新LiveData实例的值,并通知任何活动的观察者有关更改的信息

上面代码使用单例提供LocationLiveData可以在Activity和Fragment之间实现共享,在onActive和onInactive中完成监听的注册和取消,当位置改变时回调Listener并调用setValue()设置LiveData的值,从而自动更新观察者中的数据,其实前面使用的MutableLiveData也是同样的一个扩展

  • 使用扩展LIveData

扩展的LiveData使用和正常使用一样,observe()方法将Fragmrnt(它是一个实例LifecycleOwner)作为第一个参数传递,使观察者绑定到Fragment的生命周期,如果Lifecycle对象未处于活动状态,则即使值发生更改,也不会调用观察者,在之后Lifecycle的对象被Destroy后,观察者被自动删除

6、源码分析

  • MutableLiveData
public class MutableLiveData extends LiveData {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

从代码中可以看出MutableLiveData知识LiveData的一个扩展类,重写了LiveData中的抽象方法,postValue()和setValue()中也只是调用了super.postValue()和super.setValue(),也就是说所有的方法都是在LiveData中实现,

  • LiveData.observe(@NonNull LifecycleOwner owner, @NonNull Observer observer)
@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        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);
    }

从第一步添加观察者observe方法开始,从参数中看到了LifecycleOwner,相信看过Lifecycler源码的(Android Jetpack框架之 Lifecycle(源码篇))应该会想到这里的作用是处理生命周期改变,在observe方法中执行了以下逻辑:

  1. 在observe中首先判断了当前Lifecycler的状态,当Destroy时即观察者不处于活跃状态,不用接收数据
  2. 创建LifecycleBoundObserver实例保存传入的LifecycleOwner和Observer,并保存在mObservers
  3. 添加LifecycleOwner的观察者,响应生命周期的变化
  • ObserverWrapper  &  LifecycleBoundObserver
private abstract class ObserverWrapper {
        final Observer mObserver;
       
        ObserverWrapper(Observer observer) {
            mObserver = observer;  // 保存观察者Observer
        }
        
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }

            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();  // 当Owner为活跃状态时回调onActive()
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive(); // 当Owner未活跃状态时回调onInactive()
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }


 class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { // 
        @NonNull final LifecycleOwner mOwner;  //保存LifecycleOwner 

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
            super(observer); // 调用父类ObserverWrapper的构造函数传递Owner
            mOwner = owner;
        }

        // 实现GenericLifecycleObserver 当生命周期改变时回调onStateChanged
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver); // DESTROYED时移除观察者
                return;
            }
            activeStateChanged(shouldBeActive());
        }


        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

上述执行的逻辑见代码中的注释,ObserverWrapper 在Owner活跃状态改变时回调onActive和onInactive方法,LifecycleBoundObserver主要利用Lifecycler的生命周期观察者GenericLifecycleObserver,前面设置了owner.getLifecycle().addObserver(wrapper)后,当生命周期改变时会回调onStateChange()方法,在生命周期为Destroy时移除Observer;

  • setValue(T value)
@MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }


 private void dispatchingValue(@Nullable ObserverWrapper initiator) {

            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
    }

setValue()中调用了dispatchingValue(),在dispatchingValue中遍历mObservers中所有的Observer,调用considerNotify()更新数据

  • considerNotify()
private void considerNotify(ObserverWrapper observer) {
        observer.mObserver.onChanged((T) mData);
    }

considerNotify()中调用mObserver的onChange()方法,这里的mObserver就是前面observe()中第二个参数的Observer,从而更新数据,简单就是说当LiveData中的数据改变时会遍历此LiveData所有的观察者,并回调onChange(),所以所有注册观察此数据的地方都会改变

  • postValue(T value)
protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }


private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

postValue()其实是在非主线程中更新数据,其实他传递的Runnable中也是调用了setValue()方法,其余的操作只是通过ArchTaskExecutor和DefaultTaskExecutor将操作切换到主线程。

LiveData的使用和源码分析到此结束了,LiveData整个过程就是两部分,一是使用LifeCycleOwner感知声明周期的变化,两一个就是储存并遍历Observer,在数据改变时回调所有的观察者,LiveData的实现还是比较简单的,希望本篇文章的分析对大家有所帮助。

你可能感兴趣的:(Android,Jetpack)