上期文章我们讲解了LiveData,知道它是一个可观察容器同时具备生命感知能力。那么它的生命感知能力又是如何实现呢?在使用LiveData进行注册observer时,是否记得其中的两个参数。其一是Observer的回调,另一个就是LifecycleOwner。它就属于Lifecycle中的一部分。
Activity/Fragment就是具有生命状态的组件,而且他们的生命状态都是由操作系统或者framework来控制的,所以我们在App中是很难来通过代码来管理他们的生命周期。如果不遵循他们的生命周期,将会很容易导致内存泄露问题。所以如果我们能够实现生命感知能力的话,将会帮助我们更好的管理与生命周期有关的逻辑,而Lifecycle就是这样一个组件。
Lifecycle
Lifecycle可以为界面/非界面组件添加生命周期状态感知,允许观察者去监听这些生命状态。Lifecycle主要通过两个枚举来追踪生命状态。
- Event:代表生命事件,是由framework层分发过来的,这些事件与Activity/Fragment中的生命回调相匹配。
- State:代表当前追踪的组件所处的生命状态。
Event与State的联系我们可以通过下面的图来进一步了解。
依赖
在使用Lifecycle之前,我们需要在App或者Module的build.gradle中添加如下代码
dependencies {
def lifecycle_version = "1.1.1"
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
}
LifecycleObserver
LifecycleObserver是一个接口,它没有任何方法,作为标志作用,同时通过注释来生成方法。我们来看下它的使用方式,首先来自定义MyLifeCycleObserver
class MyLifeCycleObserver(private val lifecycle: Lifecycle) : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun create() {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)) {
//todo ...
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start() {
//todo ...
}
}
这里需要在自定义的方法上使用@OnLifecycleEvent注释来标明这是一个与生命周期状态相关的方法回调;同时通过Lifecycle.Event,即Event枚举,来精确定位到某一个生命周期的回调方法。
上面代码分别定位到了ON_CREATE与ON_START,即Activity/Fragment的onCreate()与onStart()方法。同时Lifecycle提供getCurrentState()方法,可以时刻查询当前的生命状态;而isAtLeast()方法则可以比较当前的生命状态是否大于等于某一个生命周期。通过这些方法能够更好的辅助我们来管理界面的生命状态。
LifecycleOwner
现在自定义的观察者MyLifeCycleObserver已经有了,接下来要做的就是对观察者进行注册监听。
class ContactsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contacts_layout)
lifecycle.addObserver(MyLifeCycleObserver(lifecycle))
}
}
通过获取Lifecycle对象来添加观察者,将我们上面自定义的MyLifeCycleObserver加入观察队列。而getLifecycle()是LifecycleOwner接口中唯一的方法。AppCompatActivity/Fragment默认实现了LifecycleOwner接口。内部通过LifecycleRegistry来注册了生命周期状态。
这样一旦界面的生命状态发生了改变,就会通知我们自定义的观察者MyLifeCycleObserver,即回调MyLifeCycleObserver中所匹配的注释方法。
不知不觉中通过Lifecycle我们已经将与生命状态相关的代码抽离到了MyLifeCycleObserver中,实现了对Activity/Fragemnt生命状态相关的解耦。
自定义LifecycleOwner
Activity/Fragment默认实现了LifecycleOwner接口,但必须是在Support Library 26.1.0之后才支持。所以如果我们想要在它之前的版本使用,需要自己实现LifecycleOwner接口。
class LifecycleActivity : Activity(), LifecycleOwner {
private lateinit var mMyLifecycle: LifecycleRegistry
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contacts_layout)
mMyLifecycle = LifecycleRegistry(this)
mMyLifecycle.markState(Lifecycle.State.CREATED)
lifecycle.addObserver(MyLifeCycleObserver(lifecycle))
}
override fun onStart() {
super.onStart()
mMyLifecycle.markState(Lifecycle.State.STARTED)
}
override fun getLifecycle(): Lifecycle = mMyLifecycle
}
首先让我们的class实现LifecycleOwner接口,然后借助LifecycleRegistry来生成一个实现Lifecycle接口的对象。如果要让我们添加的Observer能够与之前一样匹配生命周期方法,我们还需为生成的Lifecycle在生命周期方法中添加标记状态。
如上代码,在onCreate()方法中使用makeState()来绑定Lifecycle.State.CREATED状态。如此,在Activity的onCreate调用的时候,我们的MyLifeCycleObserver中的注释onCreate方法也会相应的回调。
所以结合LifecycleObserver、LifecycleOwner与LifecycleRegistry,我们可以为任意非生命感知的组件实现生命感知能力,这样一来就能更好的帮助我们对组件的生命周期进行管理。减少逻辑处理与不必要的异常发生。
Lifecycle & LiveData
那么再回到文章最初所说的LiveData,我们来分析LiveData是如何借助Lifecycle来实现生命感知能力。
在这之前,假设你已经对LiveData有一定的了解,或者你可以查看Android Architecture Components Part2:LiveData进一步了解LiveData
首先我们来看下LiveData的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);
}
在上面代码中我们看到了许多熟悉的代码,显而易见它也是通过自定义一个LifecycleBoundObserver,然后将其添加到Lifecycle的监听队列中。一旦生命周期发生变化就会回调LifecycleBoundObserver中的方法。而LifecycleBoundObserver实现了GenericLifecycleObserver接口。
public interface GenericLifecycleObserver extends LifecycleObserver {
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/
void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
}
在GenericLifecycleObserver我们看到了熟悉的LifecycleObserver。本质与文章之前我们自己自定义的MyLifeCycleObserver相同。不同的是它提供了onStateChanged()方法。该方法就是Lifecycle观察到生命周期改变时通知Observer的回调方法。
Observer明白了,现在再来看下最初的Lifecycle到底是什么?现在我们知道的是它来自于Activity/Fragment,我们到Activity中寻找(Fragment也是一样)。最后在继承的SupportActivity中找到了我们所需要的。
public class SupportActivity extends Activity implements LifecycleOwner {
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
...
...
...
@CallSuper
@Override
protected void onSaveInstanceState(Bundle outState) {
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
super.onSaveInstanceState(outState);
}
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
...
...
}
我们再一次看到了LifecycleRegistry与LifecycleOwner,它的用法也与上面提及的自定义LifecycleOwner如出一辙,这里就不多做说明。我们再来看下它与Observer的连接。
如上所示当Activity的onSaveInstanceState回调时会调用markState()方法,而在其方法调用内部,最终会来到ObserverWithState。
static class ObserverWithState {
State mState;
GenericLifecycleObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.getCallback(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
通过dispatchEvent()的方法来调用mLifecycleObserver,仔细看这个Observer就是GenericLifecycleObserver,所以它会调用onStateChanged()方法。
到这里LifecycleObserver与LifecycleOwner就完美结合在一起了,为LiveData实现了生命状态的感知能力。通过LiveData与Lifecycle的运用,我们看到了Lifecycle的灵活性与它的强大生命感知能力,这样我们就可以为任意一个自定义组件或者其他的数据容器来实现生命感知能力。Lifecycle的强大毋庸置疑。
其次要说明的是LiveData与Lifecycle的运用不仅如此,这只是它的注册监听,而我们真正使用的是它的postValue()与setValue()。由于本篇文章主要是分析Lifecycle,所以这里就不多做分析。
文章中的代码都可以在Github中获取到。使用时请将分支切换到feat_architecture_components
最后做个预告,接下来我们要了解的是AAC中的ViewModel,相信你也会马上喜欢上它。
相关文章
Android Architecture Components Part1:Room
Android Architecture Components Part2:LiveData
Android Architecture Components Part4:ViewModel
关注
私人博客