一、 LiveData简介
LiveData是Jetpack架构组件Lifecycle 库的一部分,是一个可感知生命周期的可察看容器类 (Observable)。与惯例的可察看类不同,LiveData 具备生命周期感知能力,这意味着它具备感知利用组件(如 Activity、Fragment 或 Service)的生命周期的能力,并且LiveData仅更新处于沉闷生命周期状态的利用组件观察者。
因而,LiveData具备如下一些特效。
- LiveData是一个持有数据的容器类,它持有的数据是能够被观察者订阅的,当数据发生变化时会告诉观察者,观察者能够是 Activity、Fragment、Service 等对象。
- LiveData 具备感知观察者的生命周期能力,并且只有当观察者处于激活状态(STARTED、RESUMED)才会接管到数据更新的告诉,在未激活时会主动解除注册观察者,以升高内存透露的危险。
- 应用 LiveData 保留数据时,因为数据和组件是拆散的,所以当组件被销毁时能够保证数据不会失落。
因而,咱们认为LiveData就是一个数据容器,它负责将数据包裹起来,使数据成为被观察者,当数据发生变化时,LiveData会告诉观察者以便观察者做出响应。
那相比其余的一些观察者技术,如RxJava什么的,LiveData有哪些劣势吗,上面是官网给出的一些长处列举。
- 确保 UI 界面始终和数据状态保持一致。
- 不会产生内存透露。观察者绑定到 Lifecycle 对象并在其相干生命周期 destroyed 后自行解除绑定。
- 不会因为 Activity 进行而产生奔溃。如 Activity执行finish办法后,它就不会收到任何LiveData 事件。
- 不再须要手动解决生命周期。UI 组件只需察看相干数据,不须要进行或复原察看,LiveData 会主动治理这些操作,因为 LiveData 能够感知生命周期状态的更改。
- 数据始终保持最新状态。在生命周期从非激活状态变为激活状态,始终保持最新数据,如后盾 Activity 在返回到前台后能够立刻收到数据的最新状态。
- 适当的配置更改。当配置产生更改(如屏幕旋转)而重建 Activity / Fragment,它会立刻收到最新的可用数据。
- 资源共享。LiveData 很适宜用于组件(Activity / Fragment)之间的通信,以及共享数据资源。
二、 LiveData与ViewModel的关系
在Jetpack架构中,ViewModel的次要作用是存储各种数据,当然,咱们也能够在ViewModel中解决一些数据逻辑。例如,咱们能够在ViewModel中对加载的数据进行某些加工操作。
而对页面来说,它并不需要关怀ViewModel中的数据逻辑,它只关怀须要展现的数据是什么,并且在数据发生变化时告诉页面数据的变动并做出相应的更新。而LiveData的作用就是包装ViewModel中数据,并让被观察者可能察看数据的变动。下图是官网Jetpack架构的示意图。
三、 LiveData的根本应用
3.1 应用步骤
LiveData的应用比较简单,次要会波及以下几个步骤:
- 创立 LiveData 实例以存储某种类型的数据,通常在ViewModel中实现。
- 定义一个具备onChanged()办法的Observer对象,当LiveData持有数据发生变化时回调该办法。通常,咱们能够在UI控制器类中创立该Observer对象,如Activity或Fragment。
- 通过应用observe()办法将上述的LiveData对象和Observer对象关联在一起。这样Observer对象就与LiveData产生了订阅关系,当LiveData数据发生变化时告诉,而在Observer更新数据,所以Observer通常是Activity和Fragment。
从上述步骤能够看出,LiveData应用了观察者模式,观察者通常是UI控制器,如Activity或Fragment,而被观察者则是LiveData包谷的数据对象, 当LiveData对象持有数据发生变化,会告诉对它订阅的所有处于沉闷状态的订阅者。
3.2 LiveData应用示例
3.2.1 创立 LiveData 对象
LiveData是一种可用于任何数据的封装容器,其中包含可实现 Collections 的对象,如 List。LiveData 对象通常存储在 ViewModel 对象中,并可通过 getter 办法进行拜访,如下所示。
public class NameViewModel extends ViewModel { private MutableLiveData<String> name; public MutableLiveData<String> getName() { if (name == null) { name = new MutableLiveData<String>(); } return name; }}
3.2.2 察看 LiveData 对象
在大多数状况下,咱们能够利用组件的 onCreate() 办法中开始察看 LiveData 对象。并且,LiveData 仅在数据产生更改时才发送更新,并且仅发送给沉闷观察者,如下所示。
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private NameViewModel model; private TextView nameTV; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); nameTV=findViewById(R.id.nameTV); model = new ViewModelProvider(this).get(NameViewModel.class); final Observer<String> nameObserver = new Observer<String>() { @Override public void onChanged(@Nullable final String newName) { nameTV.setText(newName); } }; model.getName().observe(this, nameObserver); }}
当咱们传递 nameObserver 参数的状况下调用 observe() 后,零碎会立刻调用 onChanged(),从而提供 mCurrentName 中存储的最新值,如果 LiveData 对象尚未在 mCurrentName 中设置值,则不会调用 onChanged()。事实上,最简略的LiveData应用办法是MutableLiveData,如下所示。
public class MainActivity extends AppCompatActivity { private static final String TAG="MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MutableLiveData<String> mutableLiveData = new MutableLiveData<>(); mutableLiveData.observe(this, new Observer<String>() { @Override public void onChanged(@Nullable final String s) { Log.d(TAG, "onChanged:"+s); } }); mutableLiveData.postValue("Android利用开发实战"); }}
3.2.3 更新 LiveData 对象
LiveData 自身没有公开可用的办法来更新存储的数据,如果须要批改LiveData的数据,能够应用MutableLiveData 类将公开 setValue(T) 和 postValue(T) 办法。通常状况下会在 ViewModel 中应用 MutableLiveData,而后 ViewModel 只会向观察者公开不可变的 LiveData 对象,如下所示。
button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String anotherName = "John Doe"; model.getCurrentName().setValue(anotherName); } });
3.2.4 扩大 LiveData
如果观察者的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于沉闷状态。以下示例代码阐明了如何扩大 LiveData 类。
public class StockLiveData extends LiveData<BigDecimal> { private StockManager stockManager; private SimplePriceListener listener = new SimplePriceListener() { @Override public void onPriceChanged(BigDecimal price) { setValue(price); } }; public StockLiveData(String symbol) { stockManager = new StockManager(symbol); } @Override protected void onActive() { stockManager.requestPriceUpdates(listener); } @Override protected void onInactive() { stockManager.removeUpdates(listener); } }
在下面的示例中,咱们首先建设一个StockLiveData并继承自LiveData,并重写了onActive和onInactive两个重要办法。
- onActivite():当有沉闷状态的订阅者订阅LiveData时会回调该办法,意味着须要在这里监听数据的变动。
- onInactive():当没有沉闷状态的订阅者订阅LiveData时会回调该办法,此时没有必要放弃StockManage服务象的连贯。
- setValue():留神到value=price这里是调用了setValue(price)办法,通过该办法更新LiveData的值,进而告诉处于沉闷状态的订阅者。
此时,LiveData会认为订阅者的生命周期处于STARTED或RESUMED状态时,该订阅者是沉闷的,那么如何应用 StockLiveData 类呢,如下所示。
public class MyFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); LiveData<BigDecimal> myPriceListener = ...; myPriceListener.observe(getViewLifeycleOwner(), price -> { // Update the UI. }); } }
以Fragment作LifecycleOwner的实例传递到observer()办法中,这样就将Observer绑定到领有生命周期的拥有者。因为LiveData能够在多个Activity、Fragment和Service中应用,所以能够创立单例模式。
public class StockLiveData extends LiveData<BigDecimal> { private static StockLiveData sInstance; private StockManager stockManager; private SimplePriceListener listener = new SimplePriceListener() { @Override public void onPriceChanged(BigDecimal price) { setValue(price); } }; @MainThread public static StockLiveData get(String symbol) { if (sInstance == null) { sInstance = new StockLiveData(symbol); } return sInstance; } private StockLiveData(String symbol) { stockManager = new StockManager(symbol); } @Override protected void onActive() { stockManager.requestPriceUpdates(listener); } @Override protected void onInactive() { stockManager.removeUpdates(listener); } }
而后,咱们就能够在 Fragment 中应用它,如下所示。
public class MyFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> { // Update the UI. }); } }
3.2.5 转换 LiveData
有时候,咱们心愿在把数据分发给观察者之前进行一些解决,或者返回一个基于已有值的LiveData对象的另外一个LiveData对象,此时就会用到 Transformations类。转化LiveData时须要用到Transformations.map()和Transformations.switchMap()等办法。
Transformations.map()
例如,上面是应用Transformations.map()办法解决LiveData存储的数据,而后将其传递给上游的示例代码。
LiveData<User> userLiveData = ...; LiveData<String> userName = Transformations.map(userLiveData, user -> { user.name + " " + user.lastName });
Transformations.switchMap()
应用Transformations.switchMap()办法同样能够扭转LiveData上游的后果,但传递给switchMap()函数的必须是一个LiveData对象,如下所示。
private LiveData<User> getUser(String id) { ...; } LiveData<String> userId = ...; LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
不过,这种转换形式是惰性的,也就是只有Observer来订阅数据的时候,才会进行转换。因而,当在ViewModel中应用一个Lifecycle对象,这种转换是一种很好的解决方案。例如,假如您有一个界面组件,该组件承受地址并返回该地址的邮政编码,那么咱们能够应用switchMap()办法进行转化。
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; private final MutableLiveData<String> addressInput = new MutableLiveData(); public final LiveData<String> postalCode = Transformations.switchMap(addressInput, (address) -> { return repository.getPostCode(address); }); public MyViewModel(PostalCodeRepository repository) { this.repository = repository } private void setInput(String address) { addressInput.setValue(address); } }
四、LiveData工作原理
通过后面的介绍,咱们晓得LiveData是一个可察看的数据持有者,并且它是具备组件生命周期感知能力的,那它是如何察看组件生命周期变动的呢?同时,LiveData仅更新处于沉闷生命周期状态的利用组件观察者,也即是说LiveData并不会告诉所有的观察者,它只会告诉处于沉闷状态的观察者,那么它是如何做到这一点的呢?
LiveData生命周期变动察看
后面介绍LiveData用法的时候提到,首先,咱们创立 LiveData 实例,而后调用LiveData的observe办法来注册观察者,将ViewModel和LiveData关联起来。observe()办法的源码如下。
@MainThread public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { assertMainThread("observe"); 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首先会判断组件以后的状态,如果状态为DESTROYED,那么间接return,这阐明DESTROYED状态的组件是不容许注册的。而后,新建一个LifecycleBoundObserver包装类,将owner和observer传了进去。接下来,将observer和LifecycleBoundObserver存储到SafeIterableMap<Observer<? super T>, ObserverWrapper>mObservers
中,留神,此处应用的是putIfAbsent办法,接下来对传入的值进行判断,如果传入key对应的value曾经存在,就返回存在的value,不进行替换,如果不存在就增加key和value,返回null。
最初,通过owner.getLifecycle().addObserver()
办法将LifecycleBoundObserver增加到Lifecycle中实现注册,这样解决之后LiveData就有了察看组件生命周期变动的能力。
LifecycleBoundObservers
LifecycleBoundObservers是LiveData的外部类,源码如下。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) { super(observer); mOwner = owner; } @Override boolean shouldBeActive() { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); } @Override boolean isAttachedTo(LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver() { mOwner.getLifecycle().removeObserver(this); } }
LifecycleBoundObserver实现了GenericLifecycleObserver接口,当组件状态发生变化时,会调用onStateChanged办法,当组件处于DESTROYED状态时,会调用removeObserver办法移除observer。
而LifecycleBoundObserver继承了ObserverWrapper类,须要重写shouldBeActive办法,用于判断以后传入的组件的状态是否是Active状态,即处于STARTED和RESUMED状态。
ObserverWrapper
ObserverWrapper是Observer的包装类,LiveData的生命周期状态监听activeStateChanged办法就定义在抽象类ObserverWrapper中,源码如下。
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; } mActive = newActive; boolean wasInactive = LiveData.this.mActiveCount == 0; LiveData.this.mActiveCount += mActive ? 1 : -1; if (wasInactive && mActive) { onActive(); } if (LiveData.this.mActiveCount == 0 && !mActive) { onInactive(); } if (mActive) { dispatchingValue(this); } } }
activeStateChanged()办法会依据Active状态和处于Active状态的组件的数量,来对onActive办法和onInactive办法进行回调,咱们能够应用这两个办法拓展LiveData对象。如果生命周期状态是Active状态,那么会调用dispatchingValue办法。
private 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; }
mDispatchingValue用于标记以后是否处于散发状态中,如果处于散发状态就会进行状态的散发,并最终调用considerNotify办法进行音讯的散发,代码如下所示。
private void considerNotify(ObserverWrapper observer) { if (!observer.mActive) { return; } if (!observer.shouldBeActive()) { observer.activeStateChanged(false); return; } if (observer.mLastVersion >= mVersion) { return; } observer.mLastVersion = mVersion; //noinspection unchecked observer.mObserver.onChanged((T) mData); }
considerNotify办法中做了屡次的判断,首先,判断ObserverWrapper的mActive值如果不为true就间接return。而后,判断以后observer对应组件的状态是不是Active,如果不是就会再次调用activeStateChanged办法并传入false,其办法外部会再次判断是否执行onActive办法和onInactive办法回调。如果判断条件都满足就持续调用Observer的onChanged办法,这个办法正是应用LiveData的observe办法的回调。