One, foreword

As we all know, activities and fragments have life cycles. If the life cycle is not well managed, there may be memory leaks. Moreover, some third-party libraries need to process corresponding things in each life cycle method, such as player mediaPlay, Hikang camera, map, positioning, Handle, etc., within the life cycle The Android Jetpack development kit was unveiled at Google IO 2018, which includes a very important lifecycle component. Lifecycle will begin with Lifecycle

With Lifecycle, you don’t have to worry about Lifecycle synchronization

2. What is Lifecycle?

Lifecycle is a life-cycle aware component that responds to Lifecycle changes in components such as activities and fragments and notifies registered observers of the changes. It helps to better organize your code, make your code logic conform to lifecycle specifications, reduce memory leaks, and improve stability.

Most application components defined in the Android framework have a life cycle. The lifecycle is managed by the framework code running in the operating system or process. They are at the heart of how Android works, and apps must follow them. Failure to do so can cause memory leaks and even application crashes.

Lifecycle is already built into new versions of AppcompatActivities and fragments, and Lifecycle is the basis for LiveData and ViewModel, the other two components in Android Jetpack. This means that the library will probably be with us for the rest of our development, so why not?

Iii. Lifecycle will be used

The API in lifecycle- Extensions is deprecated. You can add the required dependencies for a particular Lifecycle artifact.

1. Add dependencies

Kotlin
    dependencies {
        val lifecycle_version = "2.4.0 - alpha02"
        val arch_version = "2.1.0."

        // ViewModel
        implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
        // LiveData
        implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
        // Lifecycles only (without ViewModel or LiveData)
        implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version")

        // Saved state module for ViewModel
        implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")

        // Annotation processor
        kapt("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
        // alternately - if using Java8, use the following instead of lifecycle-compiler
        implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")

        // optional - helpers for implementing LifecycleOwner in a Service
        implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version")

        // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
        implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")
        // optional - ReactiveStreams support for LiveData
        implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version")

        // optional - Test helpers for LiveData
        testImplementation("androidx.arch.core:core-testing:$arch_version")}Copy the code
Java
    dependencies {
        val lifecycle_version = "2.4.0 - alpha02"
        val arch_version = "2.1.0."

        // ViewModel
        implementation("androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version")
        // LiveData
        implementation("androidx.lifecycle:lifecycle-livedata:$lifecycle_version")
        // Lifecycles only (without ViewModel or LiveData)
        implementation("androidx.lifecycle:lifecycle-runtime:$lifecycle_version")

        // Saved state module for ViewModel
        implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")

        // Annotation processor
        annotationProcessor("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
        // alternately - if using Java8, use the following instead of lifecycle-compiler
        implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")

        // optional - helpers for implementing LifecycleOwner in a Service
        implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version")

        // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
        implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")

        // optional - ReactiveStreams support for LiveData
        implementation("androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version")

        // optional - Test helpers for LiveData
        testImplementation("androidx.arch.core:core-testing:$arch_version")}Copy the code

2. Create an Observer

class AppLifecycleListener : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public fun connectOnCreate(a){
        System.out.println("connectOnCreate================")}@OnLifecycleEvent(Lifecycle.Event.ON_START)
    public fun connectOnStart(a){
        System.out.println("connectOnStart================")}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public fun connectOnResume(a){
        System.out.println("connectOnResume================")}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public fun connectOnPause(a){
        System.out.println("connectOnPause================")}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public fun connectOnStop(a){
        System.out.println("connectOnStop================")}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public fun connectOnDestroy(a){
        System.out.println("connectOnDestroy================")}Copy the code

3. Bind Observer

class MainActivity : AppCompatActivity(), LifecycleOwner {

   
    private lateinit var appLifecycleListener: AppLifecycleListener

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
       
        appLifecycleListener = AppLifecycleListener()
        lifecycle.addObserver(appLifecycleListener)
    }
}

Copy the code

4. Specific cases

Lifecycle will be written as before (officially Java code)

Amap shows

public class MainActivity extends Activity {

  MapView mMapView = null;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main);
    // Get the map control reference
    mMapView = (MapView) findViewById(R.id.map);
    // Execute mmapView. onCreate(savedInstanceState) when the activity executes onCreate
    mMapView.onCreate(savedInstanceState);
  }
  
  @Override
  protected void onDestroy(a) {
    super.onDestroy();
    // Execute mmapView.ondestroy () while the activity executes onDestroy to destroy the map
    mMapView.onDestroy();
  }
  
 @Override
 protected void onResume(a) {
    super.onResume();
    // Execute mmapView.onresume () while the activity is executing onResume to redraw the loading map
    mMapView.onResume();
    }
    
 @Override
 protected void onPause(a) {
    super.onPause();
    // Execute mmapView.onpause () while the activity is executing onPause to pause the drawing of the map
    mMapView.onPause();
    }
    
 @Override
 protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    . / / the activity execution when performing a onSaveInstanceState mMapView onSaveInstanceState (outState), save the current state of the mapmMapView.onSaveInstanceState(outState); }}Copy the code
Lifecycle after use (Kotlin)

So easy(no onSaveInstanceState method)

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(MapLifecycle(mapView, savedInstanceState))
    }
Copy the code
  • MapLifecycle
class MapLifecycle(private val mMapView: MapView.val savedInstanceState: Bundle?). :LifecycleObserver {

	// This method can be used in onCreate() if it is only used in an activity. This method can be used in onCreate() if it is used in an activity
    init {
        mMapView.onCreate(savedInstanceState)
        LogUtil.e("MapLifecycle---------init()")
        // You can initialize map styles, etc
        initMap()
    }

    private fun initMap(a) {
        val aMap = mMapView.map
        
        aMap.apply {
            myLocationStyle = MyLocationStyle().apply {
                // Set the positioning type to follow mode
                myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER)
                // Customize the blue dot icon
// myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_map_loction))
                // Customize the precision range of the circular border color
                strokeColor(Color.alpha(0))
                // Customize the width of the circular border within the precision range
                strokeWidth(1f)
                // Set the fill color of the circle
                radiusFillColor(Color.argb(0.0.0.0))
            }
            isMyLocationEnabled = false// Set to true to show the location layer and trigger the location, false to hide the location layer and not trigger the location, the default is false
/ / setOnMyLocationChangeListener (this) / / set the SDK comes with positioning news listening
            uiSettings.apply {
                isMyLocationButtonEnabled = false// Set whether the default location button is displayed.
                isZoomControlsEnabled = false// Whether the zoom button is allowed to be displayed
                isRotateGesturesEnabled = false// Do not rotate to prevent mark Angle and path misalignment
            }
            moveCamera(CameraUpdateFactory.zoomTo(17f)) The map has 17 zoom levels ranging from 3 to 19. The higher the number, the more detailed the map.}}@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate(a) {
        LogUtil.e("MapLifecycle---------onCreate()")}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun onResume(a) {
        mMapView.onResume()
        LogUtil.e("MapLifecycle---------onResume()")}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause(a) {
        mMapView.onPause()
        LogUtil.e("MapLifecycle---------onPause()")}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy(a) {
        mMapView.onDestroy()
        LogUtil.e("MapLifecycle---------onDestroy()")}}Copy the code

Lifecycle source code analysis

Lifecycle is a class that stores information about the Lifecycle state of a component, such as an Activity or Fragment, and allows other objects to observe that state.

Lifecycle uses two main enumerations to track the Lifecycle state of its associated components: the Lifecycle class

ublic abstract class Lifecycle {
    // Add an observer
    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);
    // Remove the observer
    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);
    // Get the current state
    public abstract State getCurrentState(a);

// Lifecycle events, corresponding to Activity lifecycle methods
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY  // Can respond to any event
    }

    // Life cycle state (Event is the Event that enters this state)
    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;

        // Determine at least one state
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0; }}Copy the code

Lifecycle tracks the Lifecycle state of its associated components using two main enumerations:

Events, lifecycle events that correspond to Activity/Fragment lifecycle methods.

State, life cycle State, and Event is an Event that enters a State.

When the Event is triggered:

ON_CREATE, ON_START, and ON_RESUME events are distributed after the LifecycleOwner method executes.

The ON_PAUSE, ON_STOP, and ON_DESTROY events are distributed before the LifecycleOwner method is called.

This ensures that LifecycleOwner is in this state.

There’s a picture on the website that’s pretty clear:

Let’s start with usage

class LifecycleDemoActivity : AppCompatActivity(a){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        // omit other code...
    
        lifecycle.addObserver(myLocationListener)
    }
}
Copy the code

== appactivity == Inheritance relationship:

androidx.appcompat.app.AppCompatActivity
    -> androidx.fragment.app.FragmentActivity
        -> androidx.activity.ComponentActivity
            -> androidx.core.app.ComponentActivity
                -> android.app.Activity

Copy the code

Lifecycle is defined in androidx.activity.Com ponentActivity:

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner.ViewModelStoreOwner.HasDefaultViewModelProviderFactory.SavedStateRegistryOwner.OnBackPressedDispatcherOwner {
        
    // omit other code...
        
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @NonNull
    @Override
    public Lifecycle getLifecycle(a) {
        returnmLifecycleRegistry; }}Copy the code

Lifecycle is LifecycleRegistry that is to say, then we will see = = LifecycleRegistry. AddObserver = = methods:

public class LifecycleRegistry extends Lifecycle {

    // omit other code...
    
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        // Initial state
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        // Encapsulate observer and initialState
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        // Put the encapsulated object into the Map
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        / /...

        if(! isReentrance) {// Core methodsync(); }}}Copy the code
private void sync(a) {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
        throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                + "garbage collected. It is too late to change lifecycle state.");
    }
    while(! isSynced()) { mNewEventOccurred =false;
        // no need to check eldest for nullability, because isSynced does it for us.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if(! mNewEventOccurred && newest ! =null
                && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}
Copy the code

The init and destroy states precede the Create, start, and Resume states.

  • The backwardPass method is used to “pass back” a page, such as rotating or closing the page. If the page is in the resume state before closing the page, then execute onPause, onStop, and onDestroy in sequence. There is a feeling of “going back”, hence the name backwardPass

  • The forwardPass method is used to “pass forward”. For example, when opening a new page, onCreate, onStart, and onResume will be executed

ReportFragment

Let’s take a look at the new version of AppCompatActivity to see how it can distribute events to LifecycleRegistry. Remember SupportActivity has this logic:

public class SupportActivity extends Activity implements LifecycleOwner {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this); }}Copy the code
public class ReportFragment extends Fragment {

    public static void injectIfNeededIn(Activity activity) {
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}@Override
    public void onStart(a) {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

    / /... Other life cycles also call Dispatch (Lifecycle.event.xxx) to distribute events

    @Override
    public void onPause(a) {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceofLifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); }}}}Copy the code

As you can see, SupportActivity adds a ReportFragment with no page. In the ReportFragment lifecycle function, Call the LifecycleRegistry. HandleLifecycleEvent () method to distribute life cycle events. To sum it up, here’s a picture:

AppCompatActivity adds a ReportFragment to its compatactivity and calls LifecycleRegistry when its lifecycle changes.handleLifecycleEventThe () method notifies LifecycleRegistry to change state, which LifecycleRegistry calls internallymoveToStateChange the state and call each LifecycleObserver.onStateChange() method notifies lifecycle changes.

  • Why not send Lifecycle events directly to Lifecycle in the SupportActivity Lifecycle function instead of adding a Fragment?

Since not all pages inherit appcompatactivities, in order to be compatible with non-appcompatactivities, a Fragment that also has a Lifecycle can be encapsulated to distribute Lifecycle events to Lifecycle.