LiveData是一个具有被观察者功能的持有数据的类。它是生命周期敏感的,会遵循应用组件(比如Activity,Fragment,Service)的声明周期,只在组件处于活跃状态的时候更新数据。
当组件的声明周期处于STARTED 或者 RESUMED时,它被认为是活跃的。
LiveData只会把数据的更新通知给活跃的观察者,不活跃的组件不会被通知。
LiveData采用观察者模式,当内部数据方式变化时会通知观察者对象。观察者是和生命周期对象绑定的,当它对应的生命周期是destroyed的时候,观察者会被自动移除。
当生命周期由不活跃变为活跃时,它会收到最新的一次数据更新。
我们可以使用单例模式继承LiveData来封装系统服务,这样就可以在应用中对它进行分享。这样只会连接一次系统服务,然后可以直接使用。
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);
}
}
当LiveData活跃的观察者由0变为1时,onActive会被调用;
当LiveData活跃的观察者由1变为0是,onInactive会被调用;
LiveData使用方法
1、在ViewModel中创建LiveData的实例,让它持有特定类型的对象。
LiveData是一个数据封装器,它适用于任何数据。
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> currentName;
public MutableLiveData<String> getCurrentName() {
if (currentName == null) {
currentName = new MutableLiveData<String>();
}
return currentName;
}
// Rest of the ViewModel...
}
2、创建一个Observer对象来观察LiveData数据的变化。我们通常在Activity或fragment中创建Observer。
public class NameActivity extends AppCompatActivity {
private NameViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
model = new ViewModelProvider(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
nameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.getCurrentName().observe(this, nameObserver);
}
}
如果 currentName已经被设置过值,那 onChanged会立刻回调,否则,onChanged不会立刻回调。
3、使用LiveData的observe()方法关联两者,这个方法也会接受一个LifecycleOwner对象。
我们也可以使用observeForever(Observer)方法,这样Observer被认为一直处于活跃状态,只能手动调用removeObserver(Observer)移除它。
LiveData没有暴露更新数据的方法,但是它的子类 MutableLiveData提供了setValue(T) 和postValue(T)用来更新数据,通常我们暴露给观察者的是LiveData。
setValue(T) 用来在主线程中更新数据,postValue(T)用来在子线程中更新数据。
LiveData转换
如果你想在数据分发给观察者之前对它进行改变或返回不同的数据类型,我们可以使用Transformations提供的map或者switchMap方法。
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
user.name + " " + user.lastName
});
private LiveData<User> getUser(String id) {
...;
}
LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
Transformations.map是基于原LiveData的值,进行一系列的操作,生产一个新的LiveData。
/**
* Returns a {@code LiveData} mapped from the input {@code source} {@code LiveData} by applying
* {@code mapFunction} to each value set on {@code source}.
* <p>
* This method is analogous to {@link io.reactivex.Observable#map}.
* <p>
* {@code transform} will be executed on the main thread.
* <p>
* Here is an example mapping a simple {@code User} struct in a {@code LiveData} to a
* {@code LiveData} containing their full name as a {@code String}.
*
* <pre>
* LiveData<User> userLiveData = ...;
* LiveData<String> userFullNameLiveData =
* Transformations.map(
* userLiveData,
* user -> user.firstName + user.lastName);
* });
* </pre>
*
* @param source the {@code LiveData} to map from
* @param mapFunction a function to apply to each value set on {@code source} in order to set
* it
* on the output {@code LiveData}
* @param <X> the generic type parameter of {@code source}
* @param <Y> the generic type parameter of the returned {@code LiveData}
* @return a LiveData mapped from {@code source} to type {@code <Y>} by applying
* {@code mapFunction} to each value set.
*/
@MainThread
public static <X, Y> LiveData<Y> map(
@NonNull LiveData<X> source,
@NonNull final Function<X, Y> mapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(mapFunction.apply(x));
}
});
return result;
}
从源码中我们可以看到调用map方法时会生成一个新的MediatorLiveData并监听原有的LiveData,当原有LiveData值发生变化时更新新LiveData的值。
Transformations.switchMap的转换函数是根据原LiveData的值,进行操作(比如网络请求或数据库操作),创建并返回LiveData。
/**
* Returns a {@code LiveData} mapped from the input {@code source} {@code LiveData} by applying
* {@code switchMapFunction} to each value set on {@code source}.
* <p>
* The returned {@code LiveData} delegates to the most recent {@code LiveData} created by
* calling {@code switchMapFunction} with the most recent value set to {@code source}, without
* changing the reference. In this way, {@code switchMapFunction} can change the 'backing'
* {@code LiveData} transparently to any observer registered to the {@code LiveData} returned
* by {@code switchMap()}.
* <p>
* Note that when the backing {@code LiveData} is switched, no further values from the older
* {@code LiveData} will be set to the output {@code LiveData}. In this way, the method is
* analogous to {@link io.reactivex.Observable#switchMap}.
* <p>
* {@code switchMapFunction} will be executed on the main thread.
* <p>
* Here is an example class that holds a typed-in name of a user
* {@code String} (such as from an {@code EditText}) in a {@link MutableLiveData} and
* returns a {@code LiveData} containing a List of {@code User} objects for users that have
* that name. It populates that {@code LiveData} by requerying a repository-pattern object
* each time the typed name changes.
* <p>
* This {@code ViewModel} would permit the observing UI to update "live" as the user ID text
* changes.
*
* <pre>
* class UserViewModel extends AndroidViewModel {
* MutableLiveData<String> nameQueryLiveData = ...
*
* LiveData<List<String>> getUsersWithNameLiveData() {
* return Transformations.switchMap(
* nameQueryLiveData,
* name -> myDataSource.getUsersWithNameLiveData(name));
* }
*
* void setNameQuery(String name) {
* this.nameQueryLiveData.setValue(name);
* }
* }
* </pre>
*
* @param source the {@code LiveData} to map from
* @param switchMapFunction a function to apply to each value set on {@code source} to create a
* new delegate {@code LiveData} for the returned one
* @param <X> the generic type parameter of {@code source}
* @param <Y> the generic type parameter of the returned {@code LiveData}
* @return a LiveData mapped from {@code source} to type {@code <Y>} by delegating
* to the LiveData returned by applying {@code switchMapFunction} to each
* value set
*/
@MainThread
public static <X, Y> LiveData<Y> switchMap(
@NonNull LiveData<X> source,
@NonNull final Function<X, LiveData<Y>> switchMapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData<Y> newLiveData = switchMapFunction.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
result.addSource(mSource, new Observer<Y>() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
从源码中看,调用switchMap时,会生产一个新的LiveData,这里我们叫做结果LiveData,结果LiveData会监听源LiveData的数据变化,当数据发生变化时会调用switchMapFunction生成一个新的LiveData,这就是为什么转换函数要返回LiveData的原因。结果LiveData同样会监听新LiveData的数据变化,当数据发生变化时,会把数据设置给结果LiveData。
我们也可以使用MediatorLiveData 实现自己的转换功能,因为它提供了监听其他LiveData的方法。
MediatorLiveData
MediatorLiveData可以用来合并多个数据源。
LiveData liveData1 = ...;
LiveData liveData2 = ...;
MediatorLiveData liveDataMerger = new MediatorLiveData<>();
liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
与addSource对应的是removeSource
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
e.plug();
}
}
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
其中mSources是一个map
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
final Observer<? super V> mObserver;
int mVersion = START_VERSION;
Source(LiveData<V> liveData, final Observer<? super V> observer) {
mLiveData = liveData;
mObserver = observer;
}
void plug() {
mLiveData.observeForever(this);
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
Source是一个封装类,集成Observer,当LiveData发生变化时会触发onChanged,从而触发传入Observer的onChanged方法。
LiveData源码
首先看observe方法
/**
* Adds the given observer to the observers list within the lifespan of the given
* owner. The events are dispatched on the main thread. If LiveData already has data
* set, it will be delivered to the observer.
* <p>
* The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
* or {@link Lifecycle.State#RESUMED} state (active).
* <p>
* If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
* automatically be removed.
* <p>
* When data changes while the {@code owner} is not active, it will not receive any updates.
* If it becomes active again, it will receive the last available data automatically.
* <p>
* LiveData keeps a strong reference to the observer and the owner as long as the
* given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
* the observer & the owner.
* <p>
* If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
* ignores the call.
* <p>
* If the given owner, observer tuple is already in the list, the call is ignored.
* If the observer is already in the list with another owner, LiveData throws an
* {@link IllegalArgumentException}.
*
* @param owner The LifecycleOwner which controls the observer
* @param observer The observer that will receive the events
*/
@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);
}
其中LifecycleBoundObserver是ObserverWrapper的一种实现,另一种实现是AlwaysActiveObserver,两者分别对应observe和observeForever。ObserverWrapper是Observer的包装类
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;
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);
}
}
}
内容比较简单,其中有回调onActive和onInactive的逻辑,需要注意。
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);
}
}
当生命周期变化时会触发onStateChanged,从而触发activeStateChanged里的逻辑。当生命周期变化时会触发当前是否活跃的判断shouldBeActive,这里判断了当前的生命周期状态。
也就是说当生命周期发生变化时,会根据当前状态设置当前Observer是否active,非active的Observer不会收到数据变化的通知。
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
// 这里调用了
dispatchingValue(null);
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
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;
}
dispatchingValue方法比较有意思,mDispatchingValue代表正在执行分发操作,如果再次分发置mDispatchInvalidated为true,结束正在分发的操作,while循环执行分发新值的操作。
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;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
先判断Observer是否活跃,不活跃则返回。
至此,LiveData的主要源码介绍完成。