LiveData的初衷:防止开发者疏忽而忘记释放监听对象。具体表现是:开发者不用在onDestory()里写unregister()了。仅此!
概念要点:
1. LiveData能绑定Activity、Fragment 或 Service的生命周期。之所以能感知是因为Activity、Fragment 或 Service事先已经实现好了Lifecycle的功能。
2. active是指Activity、Fragment 或 Service处于started或者resumed。其他状态就是inactive。
3. LiveData仅更新处于active(活跃状态)的observer,而inactive(非活跃状态)的observer就不会接到更新。
4. 绑定生命周期后,就不需要手动remove observer。
5. LiveData也可以不绑定Activity、Fragment 或 Service的生命周期,而一直处于active状态。但是这就需要开发者手动remove observer。
6. 存在粘性事件问题。只要一监听,旧值就会传过来。无法设置或取消粘性事件。 所以要考虑到自己的业务适配问题。
7. postValue()是异步方法,存在吞值问题。如果旧值还没有分发到UI线程。那就会被新值覆盖。
创建 LiveData 对象
LiveData可以封装对象类型的数据,也包括各种List类型。
LiveData 对象通常存储在 ViewModel 对象中,可以避免 Activity 和 Fragment 过于庞大。 功能划分上,Activity 和 Fragment 只负责显示数据,ViewModel负责存储数据状态。
现在Databinding已经算成熟了,用Databinding基本可以替代LiveData在ViewModel中的作用了。当然不排除业务上还有用的到LiveData的场景。
在ViewModel 中可通过 getter 方法进行访问,如以下示例中所示:
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...
}
更新 LiveData 对象
LiveData是抽象类,也没有公开 setValue(T) 和 postValue(T) 。是通过MutableLiveData 类才公开了 setValue(T) 和 postValue(T) 方法,可以修改存储在 LiveData 对象中的值。
setValue(T) 主线程调用。postValue(T)可以在后台线程调用,最终会回调到主线程。
通常情况下会在 ViewModel 中使用 MutableLiveData,然后 ViewModel 只会向观察者公开不可变的 LiveData 对象。
扩展 LiveData
这个主题讲的是如何利用好onActive()/onInactive() 这两个回调方法。这种方式是很有用的,如果是register/unregiser的业务,可以首先想到扩展LiveData的onActive()/onInactive() 来简化UI上的代码。
以下示例代码说明了如何扩展 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);
}
}
本例中的价格监听器实现包括以下重要方法:
当 LiveData 对象具有活跃观察者时,会调用 onActive() 方法。这意味着,从此方法开始观察股价更新。
当 LiveData 对象没有任何活跃观察者时,会调用 onInactive() 方法。由于没有观察者在监听,因此没有理由与 StockManager 服务保持连接。
setValue(T) 方法将更新 LiveData 实例的值,并将更改通知给任何活跃观察者。
使用 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.
});
}
}
observe() 方法将与 Fragment关联的 LifecycleOwner 作为第一个参数传递。这样做表示此观察者已绑定到与所有者关联的 Lifecycle 对象,这意味着:
- 如果
Lifecycle
对象未处于活跃状态,那么即使值发生更改,也不会调用观察者。 - 销毁
Lifecycle
对象后,会自动移除观察者。
LiveData
对象具有生命周期感知能力,这一事实意味着您可以在多个 Activity、Fragment 和 Service 之间共享这些对象。为使示例保持简单,可以将 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);
}
}
在 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.
});
}
}
以上是来自官方的例子。
再举一个网络连接的例子:
public class NetworkLiveData extends LiveData<NetworkInfo> {
private Context mContext;
private static NetworkLiveData mNetworkLiveData;
private NetworkReceiver mNetworkReceiver;
private final IntentFilter mIntentFilter;
private NetworkLiveData() {
mNetworkReceiver = new NetworkReceiver();
mIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
}
@MainThread
public static NetworkLiveData get() {
if (mNetworkLiveData == null) {
mNetworkLiveData = new NetworkLiveData();
}
return mNetworkLiveData;
}
public NetworkLiveData with(Context context) {
mContext = context.getApplicationContext();
return mNetworkLiveData;
}
@Override
protected void onActive() {
super.onActive();
mContext.registerReceiver(mNetworkReceiver, mIntentFilter);
}
@Override
protected void onInactive() {
super.onInactive();
mContext.unregisterReceiver(mNetworkReceiver);
}
private static class NetworkReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager manager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
get().with(context).setValue(activeNetwork);
}
}
}
最后是源码解析:
LiveData类代码,即使包括了大量的注释也就492行代码。因为系统的Activity/fragment已经实现好了lifecycle的功能。所以代码也就大大简化了。
上面的UML图阐述了基本结构。
LiveData类
这个抽象类有下面几个重要方法:
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
向LiveData添加观察者。其中LifecycleOwner 就是activity和fragment,因为它们实现了Lifecycle。
public void observeForever(@NonNull Observer<? super T> observer)
与observe不同,observeForever没有生命周期,它永远都是活跃状态,所以只要有数据更新就一定能接收到。因为没有生命周期控制,所以需要开发者手动removeObserver(observer)。
protected void setValue(T value)
protected void postValue(T value)
这两个方法分别实现数据更新。更新后观察者observer如果是活跃状态就能接到数据。setValue要在主线程调用,postValue可以在其他线程下调用。
这两个方法是protected的,需要继承后才能使用。MutableLiveData类就是干了这事,也只干了这事。
protected void onActive() //Called when the number of active observers change to 1 from 0. 有第一活跃观察者的时候调用。
protected void onInactive() //Called when the number of active observers change from 1 to 0. 一个活跃观察者都没有的时候。
这两个方法是和生命周期联系在一起的,也是扩展LiveData的时候使用的。前面有讲到它们的作用。
但是和observeForever是没有关系的。因为observeForever永远是活跃状态。
public void removeObserver(@NonNull final Observer<? super T> observer)
public void removeObservers(@NonNull final LifecycleOwner owner)
上面两个方法就是移除观察者。在MediatorLiveData中也有用到。请看后面一篇文章。
之所以开发者不需要手动调removeObserver,是因为LifecycleBoundObserver类在接到DESTORYED状态后,调用了removeObserver。
在removeObserver中,
removed.detachObserver();//mOwner.getLifecycle().removeObserver(this);移除Lifecycle的监听 removed.activeStateChanged(false);//设置非活跃状态。看看是否是最后一个活跃的,如果是就调用onInactive。
除了方法外,还有一个重要的参数:
private volatile Object mData = NOT_SET;
LiveData封装的值。观察者观察的目标对象。
private int mVersion = START_VERSION;
也就是mData的version。mVersion 决定了是不是要通知活跃观察者更新数据。会和Observer接收到的data version比较,也就是mLastVersion。初始是START_VERSION == -1
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
存储了所有的观察者,包括活跃的和非活跃的。
ObserverWrapper类
这个抽象类是对Observer的封装。
封装了什么呢?
1. mLastVersion, 用于和LiveData的mVersion比较。
2. mActive,记录是否活跃状态。
3. 可以桥接Lifecycle, 获得LifecycleOwner的实时状态,用activeStateChanged接收Lifecycle状态,决定是否调用active/inactive,以及分发更新的数据。
4.用 abstract boolean shouldBeActive();定义活跃状态。在此也可以定义永远是活跃状态,只要返回true就可以了。
LifecycleBoundObserver类
这个类中正式桥接了Lifecycle。
1. 实现了GenericLifecycleObserver。LifecycleOwner会返回Lifecycle状态。
2. 定义了活跃状态。mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
3. 用onStateChanged接受Lifecycle状态。如果是DESTORYED就移除监听。用activeStateChanged去分发状态。
AlwaysActiveObserver类
这个类是没有生命周期的。它始终是活跃状态。是个observerForever()相对应的。