Android-Architecture-Component(LiveData)

简介

简单地说,LiveData是一个数据持有类。它具有以下特点:

  • 数据可以被观察者订阅
  • 能够感知组件(Fragment、Activity、Service)的生命周期
  • 只有在组件出于激活状态(STARTED、RESUMED)才会通知观察者有数据更新

优点

  • 能够保证数据和UI统一
    这个和LiveData采用了观察者模式有关,LiveData是被观察者,当数据有变化时会通知观察者(UI)
  • 减少内存泄漏
    这是因为LiveData能够感知到组件的生命周期,当组件处于DESTROYED状态时,观察者对象会被清除掉。
  • 当Activity停止时不会引起崩溃
    这是因为组件处于非激活状态时,不会收到LiveData中数据变化的通知。
  • 不需要额外的手动处理来响应生命周期的变化
    这一点同样是因为LiveData能够感知组件的生命周期,所以就完全不需要在代码中告诉LiveData组件的生命周期状态。
  • 组件和数据相关的内容能实时更新
    组件在前台的时候能够实时收到数据改变的通知,这是可以理解的。当组件从后台到前台来时,LiveData能够将最新的数据通知组件,这两点就保证了组件中和数据相关的内容能够实时更新。
  • 针对configuration change时,不需要额外的处理来保存数据
    我们知道,当你把数据存储在组件中时,当configuration change(比如语言、屏幕方向变化)时,组件会被recreate,然而系统并不能保证你的数据能够被恢复的。当我们采用LiveData保存数据时,因为数据和组件分离了。当组件被recreate,数据还是存在LiveData中,并不会被销毁。
  • 资源共享
    通过继承LiveData类,然后将该类定义成单例模式,在该类封装监听一些系统属性变化,然后通知LiveData的观察者,这个在继承LiveData中会看到具体的例子。

LiveData的使用

使用LiveData对象

使用LiveData对象主要有以下几个步骤:

  • 创建保存特定数据类型的LiveData实例;
  • 创建Observer对象,作为参数传入LiveData.observe()方法添加观察者;
  • 更新Livedata对象存储的数据;

    创建LiveData实例

    Android文档中建议LiveData配合ViewModel使用更加哦,其实呢,你也可以不使用ViewModel,但是一定要做到LiveData中保存的数据和组件分离,至于原因,前面我们已经提到过了。下面是在ViewModel中创建LiveData实例的例子:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class NameViewModel extends ViewModel{
    // Create a LiveData with a String
    private MutableLiveData<String> mCurrentName;
    // Create a LiveData with a String list
    private MutableLiveData<List<String>> mNameListData;

    public MutableLiveData<String> getCurrentName() {
    if (mCurrentName == null) {
    mCurrentName = new MutableLiveData<>();
    }
    return mCurrentName;
    }

    public MutableLiveData<List<String>> getNameList(){
    if (mNameListData == null) {
    mNameListData = new MutableLiveData<>();
    }
    return mNameListData;
    }
    }

在NameViewModel中创建了两个MutableLiveData(MutableLiveData是LiveData的子类)实例,分别存储当前姓名、姓名列表;两个实例通过NameViewModel中的getter方法得到。

创建Observer对象,添加观察者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class LiveDataFragment extends Fragment {
private static final String TAG = "LiveDataFragment";
private NameViewModel mNameViewModel;
@BindView(R.id.tv_name)
TextView mTvName;

public static LiveDataFragment getInstance(){
return new LiveDataFragment();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNameViewModel = ViewModelProviders.of(this).get(NameViewModel.class);
mNameViewModel.getCurrentName().observe(this,(String name) -> {
mTvName.setText(name);
Log.d(TAG, "currentName: " + name);
}); // 订阅LiveData中当前Name数据变化,以lambda形式定义Observer
mNameViewModel.getNameList().observe(this, (List<String> nameList) -> {
for (String item : nameList) {
Log.d(TAG, "name: " + item);
}
}); // 订阅LiveData中Name列表数据变化,以lambda形式定义Observer
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_livedata, container, false);
ButterKnife.bind(this, view);
return view;
}

}

在onCreate()方法中通过LiveData.observe()方法添加观察者,当数据变化时会通过回调方法通知观察者,在lambda表达式中更新当前姓名和打印姓名列表。

更新LiveData中的数据

在上面我们已经订阅了LiveData数据变化,现在我们看下如果LiveData数据变化时,上面的lambda表达式中是否会受到更新的通知。我们在LiveDataFragment中增加两个按钮来改变LiveData中的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@OnClick({R.id.btn_change_name, R.id.btn_update_list})
void onClicked(View view){
switch (view.getId()){
case R.id.btn_change_name:
mNameViewModel.getCurrentName().setValue("Jane");
break;
case R.id.btn_update_list:
List<String> nameList = new ArrayList<>();
for (int i = 0; i < 10; i++){
nameList.add("Jane<" + i + ">");
}
mNameViewModel.getNameList().setValue(nameList);
break;
}
}

代码很简单,在两个按钮的点击事件中通过LiveData.setValue()方法来改变LiveData中保存的数据。当点击这两个按钮的时候,我们会发现在onCreate()方法中会收相应到数据改变的回调。

继承LiveData类

除了直接使用LiveDatad对象外,我们还可以通过集成LiveData类来定义适合特定需求的LiveData。下面继承LiveData类的例子,验证下LiveData的其中一个优点——资源共享。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class MyLiveData extends LiveData<Integer> {
private static final String TAG = "MyLiveData";
private static MyLiveData sData;
private WeakReference<Context> mContextWeakReference;

public static MyLiveData getInstance(Context context){
if (sData == null){
sData = new MyLiveData(context);
}
return sData;
}

private MyLiveData(Context context){
mContextWeakReference = new WeakReference<>(context);
}

@Override
protected void onActive() {
super.onActive();
registerReceiver();
}

@Override
protected void onInactive() {
super.onInactive();
unregisterReceiver();
}

private void registerReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mContextWeakReference.get().registerReceiver(mReceiver, intentFilter);
}

private void unregisterReceiver() {
mContextWeakReference.get().unregisterReceiver(mReceiver);
}


private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action = " + action);
if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
int wifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
int wifiLevel = WifiManager.calculateSignalLevel(
wifiRssi, 4);
sData.setValue(wifiLevel);
}
}
};
}

MyLiveData是个继承了LiveData的单例类,在onActive()和onInactive()方法中分别注册和反注册Wifi信号强度的广播。然后在广播接收器中更新MyLiveData对象。在使用的时候就可以通过MyLiveData.getInstance()方法,然后通过调用observe()方法来添加观察者对象,订阅Wifi信息强度变化。

  • onActive(),此方法是当处于激活状态的observer个数从0到1时,该方法会被调用。
  • onInactive() ,此方法是当处于激活状态的observer个数从1变为0时,该方法会被调用。

LiveData原理

  • MediatorLiveData继承自MutableLiveData,MutableLiveData继承自LiveData。MediatorLiveData可以看成是多个LiveData的代理,当将多个LiveData添加到MediatorLiveData,任何一个LiveData数据发生变化时,MediatorLiveData都会收到通知。
  • LiveData有个内部类LifecycleBoundObserver,它实现了GenericLifecycleObserver,而GenericLifecycleObserver继承了LifecycleObserver接口。在这里可以回顾下Lifecycle组件相关的内容。当组件(Fragment、Activity)生命周期变化时会通过onStateChanged()方法回调过来。
  • Observer接口就是观察者,其中定义了LiveData数据变化的回调方法onChanged()。

Observer

LiveData 应用的主要是观察者模式,因为数据是多变的,所以肯定需要观察者来观察。而观察者和数据源建立连接就是通过 observe 方法来实现的。

1
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>();

这个 LiveData 的所有观察者 Observer 都会被保存在 mObservers 这个 map 里面。那么对应的 value 值 ObserverWrapper 又是什么东西呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private abstract class ObserverWrapper {
final Observer<T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;

ObserverWrapper(Observer<T> observer) {
mObserver = observer;
}

...

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;
// 如果现在第一次新增活跃的观察者,那么回调 onActive ,onActive 是个空方法
if (wasInactive && mActive) {
onActive();
}
// 如果现在没有活跃的观察者了,那么回调 onInactive ,onInactive 是个空方法
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
// 向观察者发送 LiveData 的值
if (mActive) {
dispatchingValue(this);
}
}
}

ObserverWrapper 是 Observer 的包装类,在 Observer 的基础上增加了 mActive 和 mLastVersion 。mActive 用来标识观察者是否是活跃,也就是说是否是在可用的生命周期内。
但是 ObserverWrapper 是个抽象类啊,到底是谁来实现它的呢?答案有两个。

  • LifecycleBoundObserver
  • AlwaysActiveObserver

我们重点来讲讲 LifecycleBoundObserver 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;

LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}

@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
// 移除观察者,在这个方法中会移除生命周期监听并回调activeStateChanged 方法
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}

@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}

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

可以看出,LifecycleBoundObserver 是把 ObserverWrapper 和 Lifecycle 相结合了。这样,在 LiveData 里就可以获取到观察者的生命周期了。当观察者的生命周期可用时,LiveData 会把数据发送给观察者,而当观察者生命周期不可用的时候,即 mOwner.getLifecycle().getCurrentState() == DESTROYED ,LiveData 就会选择不发送,并且自动解绑,防止造成内存泄漏等问题。

最后补充一下,LiveData 认为观察者生命周期可用的依据就是在 onStart 调用之后,在 onPause 调用之前。

平时使用 observe 的就是直接利用的是 LifecycleBoundObserver ,而另一个 AlwaysActiveObserver 顾名思义就是一直是活跃的,和观察者的生命周期无关了。我们调用 observeForever 方法内部使用的就是 AlwaysActiveObserver 。

observe

顺便,我们把 observe 方法也一起看了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> 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);
}

代码比较简单,就是利用了之前我们分析的 LifecycleBoundObserver ,再把它保存到 map 中。
最后,将 LifecycleBoundObserver 的生命周期监听注册好,OK,万事具备。
还有,另外一个 observeForever 方法就不看了,和 observe 方法差不多。

setData or postData

setData 或者 postData 是当数据改变后向观察者传递值的。postData 最后也会调用 setData ,所以在这我们就只看 setData 了。

1
2
3
4
5
6
7
8
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
// mData 保存的就是改变后的数据
mData = value;
dispatchingValue(null);
}

发现这个 setData 的代码中判断了是否是主线程,所以这个方法只能在主线程中调用了。另外,调用后相应的版本也会自增。最后就是调用 dispatchingValue 方法去分发这个数据 mData 了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}

在 dispatchingValue 就是循环遍历 mObservers 这个 map ,向每一个观察者都发送新的数据。具体的代码在 considerNotify 方法中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
//noinspection unchecked
// 调用 Observer 的 onChanged 方法实现回调
observer.mObserver.onChanged((T) mData);
}

好啦,到这里就把 LiveData 整个流程讲的差不多了。当然还有一些细节没讲到,感兴趣的同学就自己回去看看源码吧。LiveData 讲完了,再说一点,我们在实际的使用中用的都是 LiveData 的实现类 MutableLiveData 。

您的支持是我原创的动力