Lifecycle is released on Android X. Lifecycle 2.4.0 and the @onlifecycleEvent annotation has been deprecated. Lifecycleevening Server or DefaultLifecycleObserver are recommended instead
Lifecycle is ubiquitous in modern Android applications and it is the presence of various Lifecycle – Aware components that ensure the robustness of the application.
Lifecycle nature is a best practice for the Observer pattern. By implementing the LifecycleObserver interface, developers can customize Lifecycle – Aware components, Aware of LifecycleOwner lifecycle callbacks such as activities or fragments.
In the light of the new release, let’s review the use of the Lifecycle annotation and the alternatives to deprecating it
Lifecycle Events & States
Lifecyce defines Event and State using two sets of enums.
- Events
- ON_CREATE
- ON_START
- ON_RESUME
- ON_PAUSE
- ON_STOP
- ON_DESTROY
- ON_ANY
- States
- INITIALIZED
- CREATED
- STARTED
- RESUMED
- DESTROYED
Events correspond to the late-life callbacks of native system components such as activities, and each Event that occurs means that these LifecycleOwners enter a new State.
The LifecycleObserver as an observer can perceive events when the LifecycleOwner being observed changes its lifecycle State. LifecycleObserver can be defined in three ways:
- implementation
LifecycleEventObserver
interface - use
@OnLifecycleEvent
annotations
Implement LifecycleEventObserver
public interface LifecycleEventObserver extends LifecycleObserver {
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
Copy the code
LifecycleEventObserver is a single-method interface that can be declared in Kotlin as a more succinctly written Lambda
val myEventObserver = LifecycleEventObserver { source, event ->
when(event) {
Lifecycle.Event.ON_CREATE -> TODO()
Lifecycle.Event.ON_START -> TODO()
else -> TODO()
}
}
Copy the code
LifecycleEventObserver itself is a derivative of LifecycleObserver and will be used directly to addObserver into LivecycleOwner’s Lifecycle.
You need to write swich/case in onStateChanged to distribute the event yourself. Compared to methods like onCreate and onResume, which are used to rewriting activities or fragments, it is a bit wordy.
So Lifecycle gave us the @onlifecycleEvent annotation
Use the @onlifecycleEvent annotation
To use it, you simply inherit the LifecycleObserver interface and add annotations to the member methods
val myEventObserver = object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onStart(a) {
TODO()
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreat(a) {
TODO()
}
}
Copy the code
After adding a registration, the Event distribution to LifecycleOwner automatically calls back the annotation matching member method, which developers love because it eliminates the manual switch/case process
Annotation parsing process
How is it that when an Event is distributed, it goes back to the annotation method?
LifecycleObserver added via addObserver is turned into a LifecycleEventObserver, and LifecycleOwner distributes the Event by calling its onStateChanged
Handle transformations in Lifecycline #lifecycleEventObserver
public class Lifecycling {
@NonNull
static LifecycleEventObserver lifecycleEventObserver(Object object) {
boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
// The observer is FullLifecycleObserver
if (isLifecycleEventObserver && isFullLifecycleObserver) {
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
(LifecycleEventObserver) object);
}
// The observer is LifecycleEventObserver
if (isFullLifecycleObserver) {
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
}
if (isLifecycleEventObserver) {
return (LifecycleEventObserver) object;
}
finalClass<? > klass = object.getClass();int type = getObserverConstructorType(klass);
// Observer is a class generated by apt
if (type == GENERATED_CALLBACK) {
List<Constructor<? extends GeneratedAdapter>> constructors =
sClassToAdapters.get(klass);
if (constructors.size() == 1) {
GeneratedAdapter generatedAdapter = createGeneratedAdapter(
constructors.get(0), object);
return new SingleGeneratedAdapterObserver(generatedAdapter);
}
GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
for (int i = 0; i < constructors.size(); i++) {
adapters[i] = createGeneratedAdapter(constructors.get(i), object);
}
return new CompositeGeneratedAdaptersObserver(adapters);
}
// The observer needs to generate a wrapper through reflection
return newReflectiveGenericLifecycleObserver(object); }...public static String getAdapterName(String className) {
return className.replace("."."_") + "_LifecycleAdapter"; }}Copy the code
The logic is clear. There is no need to convert LifecycleEventObserver to different LifecycleObserver types.
Use a pseudocode to comb as follows:
if (lifecycleObserver is FullLifecycleObserver) {
return FullLifecycleObserverAdapter // More on that later
} else if (lifecycleObserver is LifecycleEventObserver) {
return this
} else if (type == GENERATED_CALLBACK) {
return GeneratedAdaptersObserver
} else {// type == REFLECTIVE_CALLBACK
return ReflectiveGenericLifecycleObserver
}
Copy the code
Annotations can be used in two ways.
Scenario 1: Use reflection to generate wrapper during Runtime
class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
private final Object mWrapped;
private final CallbackInfo mInfo;
ReflectiveGenericLifecycleObserver(Object wrapped) {
mWrapped = wrapped;
mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
}
@Override
public void onStateChanged(LifecycleOwner source, Event event) { mInfo.invokeCallbacks(source, event, mWrapped); }}Copy the code
CallbackInfo is the key, collecting callback information for the current LifecycleObserver through reflection. OnStateChanged does not get an error because method is missing when called through reflection.
Scenario 2: Use APT to generate className + _LifecycleAdapter at compile time
In addition to utilizing reflection, Lifecycle also provides apt methods for handling annotations.
Add a Gradle dependency:
dependencies {
/ / Java
annotationProcessor "Androidx. Lifecycle: lifecycle - compiler: 2.3.1." "
/ / kotlin writing
kapt "Androidx. Lifecycle: lifecycle - compiler: 2.3.1." "
}
Copy the code
The compiler will then generate a class with the _LifecycleAdapter suffix based on the LifecyceObserver class name. For example, if we annotate onCreat and onStart, the generated code looks like this:
public class MyEventObserver_LifecycleAdapter implements GeneratedAdapter {
final MyEventObserver mReceiver;
MyEventObserver_LifecycleAdapter(MyEventObserver receiver) {
this.mReceiver = receiver;
}
@Override
public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny,
MethodCallsLogger logger) {
booleanhasLogger = logger ! =null;
if (onAny) {
return;
}
if (event == Lifecycle.Event.ON_CREATE) {
if(! hasLogger || logger.approveCall("onCreate".1)) {
mReceiver.onCreate();
}
return;
}
if (event == Lifecycle.Event.ON_START) {
if(! hasLogger || logger.approveCall("onStart".1)) {
mReceiver.onStart();
}
return; }}}Copy the code
Apt reduces the number of reflected calls, gives better performance, and of course sacrifices some compile speed.
Why use annotations
There are many types of events in the lifecycle, and we often do not need to implement them all. If we do not use annotations, we may need to implement all methods, resulting in extra useless code
The FullLifecycleObserver in the code above is an interface to all methods
interface FullLifecycleObserver extends LifecycleObserver {
void onCreate(LifecycleOwner owner);
void onStart(LifecycleOwner owner);
void onResume(LifecycleOwner owner);
void onPause(LifecycleOwner owner);
void onStop(LifecycleOwner owner);
void onDestroy(LifecycleOwner owner);
}
Copy the code
As we can see from the fact that the interface is not public (Java code), there is no intention for us to use such an interface, adding to the burden of developers.
Reasons for abandonment
If the notes are so good, why scrap them?
This annotation required the usage of code generation or reflection, which should be avoided.
As you can see from the comments in the official documentation, annotations either rely on reflection to reduce runtime performance or APT to reduce compile speed, which is not a perfect solution.
We introduced annotations simply because we didn’t want to implement more than a few empty methods. Early Android projects do not support Java8 compilation, interface does not have the default method, now Java8 is the default configuration, you can add the default method to the interface, at this time annotations have lost the meaning of existence.
It is now officially recommended to use the DefaultLifecycleObserver interface to define your LifecycleObserver
public interface DefaultLifecycleObserver extends FullLifecycleObserver {
@Override
default void onCreate(@NonNull LifecycleOwner owner) {}@Override
default void onStart(@NonNull LifecycleOwner owner) {}@Override
default void onResume(@NonNull LifecycleOwner owner) {}@Override
default void onPause(@NonNull LifecycleOwner owner) {}@Override
default void onStop(@NonNull LifecycleOwner owner) {}@Override
default void onDestroy(@NonNull LifecycleOwner owner) {}}Copy the code
FullLifecycleObserverAdapter, mindless callback FullLifecycleObserver can
class FullLifecycleObserverAdapter implements GenericLifecycleObserver {
private final FullLifecycleObserver mObserver;
FullLifecycleObserverAdapter(FullLifecycleObserver observer) {
mObserver = observer;
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
switch (event) {
case ON_CREATE:
mObserver.onCreate(source);
break;
case ON_START:
mObserver.onStart(source);
break;
case ON_RESUME:
mObserver.onResume(source);
break;
case ON_PAUSE:
mObserver.onPause(source);
break;
case ON_STOP:
mObserver.onStop(source);
break;
case ON_DESTROY:
mObserver.onDestroy(source);
break;
case ON_ANY:
throw new IllegalArgumentException("ON_ANY must not been send by anybody"); }}}Copy the code
Note DefaultLifecycleObserver also can be used before the 2.4.0, exists in androidx. Lifecycle. The lifecycle – common – java8 this repository, 2.4.0 began to unified mobile androidx. Lifecycle. Lifecycle – common, has no java8 separate extension libraries.