Introduction and use of Lifecycle
Before introducing LiveData and ViewModel, we need to know Lifecycle.
What is Lifecycle? Why do I need a Lifecycle?
We all know that in Android development, both Activity, Fragment and Service have life cycles.
Just like we often initialize a component in onCreate, start it in onStart, stop it in onPause, and destroy it in onDestroy.
These large and small operation processes, step by step, contribute to the life system of the software, and once disrupted, they may have the following effects:
-
Memory leaks (software crashes, phone out of memory, etc.)
-
Application crash (unresponsive, flicker, etc.)
-
Carton (running memory soars in a flash, phone gets hot, etc.)
Take one officially mentioned chestnut (for mobile location information):
In the absence of Lifecycle, we did this:
/// MyLocationListener class MyLocationListener( private val context: Context, private val callback: (Location) -> Unit ) { fun connect() { /// todo start connection } fun disconnect() { /// todo disconnect } } /// LocationActivity class LocationActivity : AppCompatActivity() { private lateinit var myLocationListener: MyLocationListener override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) myLocationListener = MyLocationListener(this) { location -> /// todo update UI } } override fun onStart() { super.onStart() myLocationListener.connect() } override fun onStop() { super.onStop() myLocationListener.disconnect() } }
As the official website said, it seems like there's nothing wrong with writing this logically, but once onStop ends before onStart (they compete), there's a possibility of a memory leak.
Also, in actual development, if functionality like the above needs to be available on other pages, you will need to write an additional copy of onStart and onStop, which is better.
Why do you say that? The code in these life cycle functions may be dozens or even hundreds of lines in actual development...
This situation mentioned above is called code coupling. In the elegant code structure which pursues high clustering and low coupling, this kind of coupling is disconnected and the whole body of code is obviously not good.
The development environments and SDK versions used in this article are listed below and should be used by readers no less than those used in this article.
Android Studio 4.0.1
minSdkVersion 21
targetSdkVersion 30
text
Referring to the above mentioned mobile location information, why not let MyLocationListener have a direct life cycle?
First code, then explain:
class MyLocationListener( private val context: Context, private val callback: (Location) -> Unit ) : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_START) fun connect() { /// todo start connection } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun disconnect() { /// todo disconnect } } class LocationActivity : AppCompatActivity() { private lateinit var myLocationListener: MyLocationListener override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) myLocationListener = MyLocationListener(this) { location -> /// todo update UI } // Join Lifecycle Observation lifecycle.addObserver(myLocationListener) } }
In this way, you can directly respond to the life cycle of an Activity in MyLocationListener.
Actor Lifecycle appears
As we mentioned above, Lifecycle, as an observer of life cycle, is able to capture activities and fragments directly when their life cycle changes and respond to the corresponding method (note above is used to implement the corresponding response).
The structure of Lifecycle is simple:
- Observer Registry inherits to Lifecycle
- Observed (Lifecycle Owner)
- Observer (Lifecycle Observer)
It's not difficult to implement logic either, holding Lifecycle Owner through Lifecycle Registry and finally adding Lifecycle Observer.
Simply put, Lifecycle Registry is the bridge that connects Lifecycle Owner to Lifecycle Observer.
The first way to write Lifecycle
Implement the Lifecycle Observer interface directly, and observe (monitor) changes to each life cycle event by annotating @OnLifecycle Event.
class MyLifecycleObserver : LifecycleObserver { private val TAG: String = "GLog" @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun onCreate(owner: LifecycleOwner) { Log.d(TAG, "onCreate, currentState = ${owner.lifecycle.currentState}") } @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onStart(owner: LifecycleOwner) { Log.d(TAG, "onStart, currentState = ${owner.lifecycle.currentState}") } @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun onResume(owner: LifecycleOwner) { Log.d(TAG, "onResume, currentState = ${owner.lifecycle.currentState}") } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun onPause(owner: LifecycleOwner) { Log.d(TAG, "onPause, currentState = ${owner.lifecycle.currentState}") } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onStop(owner: LifecycleOwner) { Log.d(TAG, "onStop, currentState = ${owner.lifecycle.currentState}") } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun onDestroy(owner: LifecycleOwner) { Log.d(TAG, "onDestroy, currentState = ${owner.lifecycle.currentState}") } @OnLifecycleEvent(Lifecycle.Event.ON_ANY) fun onAny(owner: LifecycleOwner) { Log.d(TAG, "onAny, currentState = ${owner.lifecycle.currentState}") } }
Then join the observer at MainActivity.kt
... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Join an observer lifecycle.addObserver(MyLifecycleObserver()) } ...
After running, you can see that LogCat has the following output:
When App enters Task View (Cut Background), LogCat results are as follows:
When App comes back to the foreground, the LogCat results are as follows:
You can see that the life cycle of MainActivity has been observed (listened on) except for onRestart for OnLifecycle Event.
In the screenshot above, you can see that onAny is executed once for each lifecycle function execution.
Lifecycle implemented by annotations is an observer implemented by reflection, independent of the method (function) name.
Implement the second way of writing Lifecycle
Looking at Lifecycle Observer, we can see that there are two subinterfaces underneath it.
Lifecycle can also be implemented by inheriting these two subinterfaces
class MyLifecycleObserverEvent : LifecycleEventObserver { private val TAG: String = "GLogEvent" override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { when (event) { Lifecycle.Event.ON_CREATE -> { Log.d(TAG, "ON_CREATE, currentState = ${source.lifecycle.currentState}") } Lifecycle.Event.ON_START -> { Log.d(TAG, "ON_START, currentState = ${source.lifecycle.currentState}") } Lifecycle.Event.ON_RESUME -> { Log.d(TAG, "ON_RESUME, currentState = ${source.lifecycle.currentState}") } Lifecycle.Event.ON_PAUSE -> { Log.d(TAG, "ON_PAUSE, currentState = ${source.lifecycle.currentState}") } Lifecycle.Event.ON_STOP -> { Log.d(TAG, "ON_STOP, currentState = ${source.lifecycle.currentState}") } Lifecycle.Event.ON_DESTROY -> { Log.d(TAG, "ON_DESTROY, currentState = ${source.lifecycle.currentState}") } Lifecycle.Event.ON_ANY -> { Log.d(TAG, "ON_ANY, currentState = ${source.lifecycle.currentState}") } } } }
Then modify MainActivity.kt
... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Join an observer //lifecycle.addObserver(MyLifecycleObserver()) lifecycle.addObserver(MyLifecycleObserverEvent()) } ...
Implement the third way of writing Lifecycle
Need to build at app level. Add the following dependencies to gradle
dependencies { ... implementation "androidx.lifecycle:lifecycle-common-java8:2.5.0" // The version number here is filled in as appropriate ... }
This writing requires Java8 support Kotlin Error Using DefaultLifecycle Observer.
Java 8 is already supported in higher versions of Android Studio.
After you join the dependency, you will find that your first writing has been discarded.
Yes, it is also officially recommended at present.
class MyDefaultLifecycleObserver : DefaultLifecycleObserver{ private val TAG: String = "GLogDefault" override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) Log.d(TAG, "onCreate, currentState = ${owner.lifecycle.currentState}") } override fun onStart(owner: LifecycleOwner) { super.onStart(owner) Log.d(TAG, "onStart, currentState = ${owner.lifecycle.currentState}") } override fun onResume(owner: LifecycleOwner) { super.onResume(owner) Log.d(TAG, "onResume, currentState = ${owner.lifecycle.currentState}") } override fun onPause(owner: LifecycleOwner) { super.onPause(owner) Log.d(TAG, "onPause, currentState = ${owner.lifecycle.currentState}") } override fun onStop(owner: LifecycleOwner) { super.onStop(owner) Log.d(TAG, "onStop, currentState = ${owner.lifecycle.currentState}") } override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) Log.d(TAG, "onDestroy, currentState = ${owner.lifecycle.currentState}") } }
Then modify MainActivity.kt again
... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Join an observer //lifecycle.addObserver(MyLifecycleObserver()) //lifecycle.addObserver(MyLifecycleObserverEvent()) lifecycle.addObserver(MyDefaultLifecycleObserver()) } ...
Here's why the third way of writing doesn't directly implement the FullLifecycleObserver interface. We can find that Ctrl+left-click on the DefaultLifecycleObserver interface class, which inherits to FullLifecycleObserver and adds the default keyword to the parent interface method.
This is a new feature of the Java8 interface Analysis of default keyword in Java8.
Implement Lifecycle in Application
Create App.kt Class Inherits Application
/// class App : Application() { override fun onCreate() { super.onCreate() ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycle()) } } /// class AppLifecycle : DefaultLifecycleObserver{ private val TAG: String = "GLog_App" override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) Log.d(TAG, "onCreate, currentState = ${owner.lifecycle.currentState}") } override fun onStart(owner: LifecycleOwner) { super.onStart(owner) Log.d(TAG, "onStart, currentState = ${owner.lifecycle.currentState}") } override fun onResume(owner: LifecycleOwner) { super.onResume(owner) Log.d(TAG, "onResume, currentState = ${owner.lifecycle.currentState}") } override fun onPause(owner: LifecycleOwner) { super.onPause(owner) Log.d(TAG, "onPause, currentState = ${owner.lifecycle.currentState}") } override fun onStop(owner: LifecycleOwner) { super.onStop(owner) Log.d(TAG, "onStop, currentState = ${owner.lifecycle.currentState}") } override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) Log.d(TAG, "onDestroy, currentState = ${owner.lifecycle.currentState}") } }
Modify AndroidManifest.xml
<application android:name=".App" ...
Implement Lifecycle in Service
/// class MyService : LifecycleService() { override fun onCreate() { super.onCreate() lifecycle.addObserver(MyLifecycleServiceObserver()) } } /// class MyLifecycleServiceObserver : DefaultLifecycleObserver { private val TAG: String = "GLog_Service" override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) Log.d(TAG, "onCreate, currentState = ${owner.lifecycle.currentState}") } override fun onStart(owner: LifecycleOwner) { super.onStart(owner) Log.d(TAG, "onStart, currentState = ${owner.lifecycle.currentState}") } override fun onResume(owner: LifecycleOwner) { super.onResume(owner) Log.d(TAG, "onResume, currentState = ${owner.lifecycle.currentState}") } override fun onPause(owner: LifecycleOwner) { super.onPause(owner) Log.d(TAG, "onPause, currentState = ${owner.lifecycle.currentState}") } override fun onStop(owner: LifecycleOwner) { super.onStop(owner) Log.d(TAG, "onStop, currentState = ${owner.lifecycle.currentState}") } override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) Log.d(TAG, "onDestroy, currentState = ${owner.lifecycle.currentState}") } }
At this point, the basic use of Lifecycle has come to an end, and subsequent LifeDatas and ViewModel s rely on it for data observation.
Talk about the implementation principle of Lifecycle
Why can I go directly through lifecycle? AddObserver() Add an observer? The aforementioned Lifecycle Registry seems to have never appeared.
The lifecycle we wrote earlier in kotlin. AddObserver() corresponds to getLifecycle().addObserver() in Java
This method is only available in the Lifecycle Owner interface.
We will find that AppCompatActivity of Android Studio default extends, whose parent FragmentActivity and ComponentActivity all implement the Lifecycle Owner interface.
And they all maintain a final Lifecycle Registry... = new Lifecycle Registry (this); A registrar that observes (listens for) changes in the life cycle through or indirectly through the moveToState method.
That's why we can get Lifecycle () directly.
Implement the Lifecycle Owner interface yourself
At this point, we can try to implement the getLifecycle() method on our own in the Lifecycle Owner interface.
First, create MainActivity2.kt and let it inherit the Activity class directly (because in the higher version API, only the Activity class does not implement the Lifecycle Owner interface), and manually implement the Lifecycle Owner interface.
class MainActivity2 : Activity(), LifecycleOwner{ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) } override fun getLifecycle(): Lifecycle { TODO("Not yet implemented") } }
Next, you need the Lifecycle Registry described earlier to modify the code
class MainActivity2 : Activity(), LifecycleOwner { private val registry: LifecycleRegistry = LifecycleRegistry(this) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) } override fun getLifecycle(): Lifecycle { return registry } }
At this point, we customize and add our Lifecycle Observer object to replicate all of its life cycle observations.
class MainActivity2Observer : DefaultLifecycleObserver { private val TAG = "MainActivity2Observer" override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) Log.d(TAG, "onCreate") } override fun onStart(owner: LifecycleOwner) { super.onStart(owner) Log.d(TAG, "onStart") } override fun onResume(owner: LifecycleOwner) { super.onResume(owner) Log.d(TAG, "onResume") } override fun onPause(owner: LifecycleOwner) { super.onPause(owner) Log.d(TAG, "onPause") } override fun onStop(owner: LifecycleOwner) { super.onStop(owner) Log.d(TAG, "onStop") } override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) Log.d(TAG, "onDestroy") } }
Add MainActivity2Observer to the registrar.
Run (don't forget to modify the first launch activity in AndroidManifest.xml)!!
Not surprisingly, it runs and the lifecycle approach is observed.
Not surprisingly, the question arises again: there is no handleLifecycle Event method in Activity like FragmentActivity, and why is life cycle observed?
First Debugger traces the getLifecycle() method and you can see that there is a line under Activity's onCreate.
Along the way, you'll find a Dispatcher ActivityCallback internal class in the Lifecycle Dispatcher class, which is onActivityCreated.
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { ReportFragment.injectIfNeededIn(activity); }
A Fragment is attached to the current activity
The life cycle changes were then observed using the dispatch method.
Reference resources: Lifecycle, you really understand this time
In summary, it is a sentence that implementing the Lifecycle Owner interface separately and replicating getLifecycle() can also enable life cycle observation.
That should be the fourth way to write Lifecycle.