Detailed explanation of the use of Lifecycle introduced by Android official architecture components

Lifecycle is used to manage and respond to changes in the life cycle of activities and fragments. We usually do some heavy operations in the life cycle methods in Activity and Fragment, so that we can manage these life cycle methods with Lifecycle. It can automatically integrate the state of the Activity and Fragment life cycle.

Add dependencies:

1. Add Maven repository to build.gradle under project

allprojects {
    repositories {
        jcenter ()
        google()//Add Google Maven repository
    }
}

2. build.gradle under app

dependencies {
    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:1.1.1"
    // alternatively, just ViewModel
    implementation "android.arch.lifecycle:viewmodel:1.1.1"
    // alternatively, just LiveData
    implementation "android.arch.lifecycle:livedata:1.1.1"

    annotationProcessor "android.arch.lifecycle:compiler:1.1.1"

    // Room (use 1.1.0-beta3 for latest beta)
    implementation "android.arch.persistence.room:runtime:1.0.0"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

    // Paging
    implementation "android.arch.paging:runtime:1.0.0-rc1"

    // Test helpers for LiveData
    testImplementation "android.arch.core:core-testing:1.1.1"

    // Test helpers for Room
    testImplementation "android.arch.persistence.room:testing:1.0.0"
}

3. Add Java 8 support 

dependencies {
    // Java8 support for Lifecycles
    implementation "android.arch.lifecycle:common-java8:1.1.1"
}

4. RXJava supports dependencies

dependencies {
    // RxJava support for Room (use 1.1.0-beta3 for latest beta)
    implementation "android.arch.persistence.room:rxjava2:1.0.0"

    // ReactiveStreams support for LiveData
    implementation "android.arch.lifecycle:reactivestreams:1.1.1"

    // RxJava support for Paging
    implementation "android.arch.paging:rxjava2:1.0.0-alpha1"
}

5. Guava dependency support

dependencies {
    // Guava support for Room
    implementation "android.arch.persistence.room:guava:1.1.0-beta3"
}
6. Lightweight Lifecycles support
dependencies {
    // Lifecycles only (no ViewModel or LiveData)
    implementation "android.arch.lifecycle:runtime:1.1.1"
    annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
}

Most of the life cycle of the application is defined in the Android Framework layer, and the management of the life cycle is handled in the operating system or the framework layer of the project. Otherwise, it will cause a memory leak or crash directly. For example: Activity is processed as follows

class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // connect to system location service
    }

    void stop() {
        // disconnect from system location service
    }
}

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    @Override
    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // update UI
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        myLocationListener.start();
        // manage other components that need to respond
        // to the activity lifecycle manage other responses of Activity
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
        // manage other components that need to respond
        // to the activity lifecycle
    }
}

However, in actual projects, we will have a lot of callbacks to manage the UI and other components that respond to the life cycle. There will be a lot of complex logic in the life cycle method, which is not conducive to the maintenance of our project. There is also no guarantee that the Activity or Fragment will execute onStart() before onStop() executes.

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, location -> {
            // update UI
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        Util.checkUserStatus(result -> {
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                myLocationListener.start();
            }
        });
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}

Lifecycle

Lifecycle not only contains the status information of the life cycle, but also allows other objects to monitor this status.

It uses two enums to relate the states of the lifecycle:

Events: It starts to distribute events from the Fragmentwork layer and the Lifecycle class, and then maps these events to the life cycle of Activity and Fragment

State: A state is the state of the tracked lifecycle.


The life cycle state of a class needs to be done through annotations. as follows

public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());

ps: myLifecycleOwner object is an object that implements the LifecycleOwner interface

LifecycleOwner

LifecycleOwner is an interface with only one getLifecycle(). In addition, there is a class that can control the entire applicationProcessLifecycleOwner

This interface has the ownership of abstracting a single class called Lifecycle, and this interface can be implemented by any class.

LicecycleObserver and LicecycleOwner are used together, one is used to provide the life cycle, and the other is used to register the observer to observe

An example is as follows:

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}

But if there are things similar to Fragment running callbacks that are opened or do other things after the Activity state is released, this is what we don't want to see, so we have to make Fragment not callback. as follows:

class MyLocationListener implements LifecycleObserver {
    private boolean enabled = false;
    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
       ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void start() {
        if (enabled) {
           // connect
        }
    }

    public void enable() {
        enabled = true;
        if (lifecycle.getCurrentState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void stop() {
        // disconnect if connected
    }
}

At this point, LocationListener has the complete life cycle of the class. If we use it in other Activity and Fragment, we only need to initialize it. In this way, all operations will be handled by its own class.

Custom LifecycleOwner

The custom implementation of LifecycleOwner must be implemented in the version of Support Library 26.1.0

Use the LifecycleRegistry to push events into a custom LifecycleOwner.

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry mLifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);

        mLifecycleRegistry = new LifecycleRegistry(this);
        mLifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        mLifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

Best Practices for Perception Components

1. Keep the Activity or Fragment simple and use ViewModel to observe data and View

2. Try to write data-driven UI, UIController will update View when data or user behavior changes, or notify ViewModel

3. ViewModel is a class designed by Google specifically for the interaction between the Model layer and the View layer. Google recommends using ViewModel for data-related logic. PS: ViewModel itself cannot manipulate data. Its essence is to call related data. component to notify the UI controller.

4. Use Data Binding or Butter Knife to save template code extraction.

5. Use the MVP pattern for decoupling

6. Avoid referencing the View or Activity context in the ViewModel to prevent memory leaks.

Use Cases for Perception Components

1. Realize direct switching between coarse-grained and fine-grained. When the Activity visible state is switched to fine-grained, when it recedes to the background (that is, invisible), coarse-grained is turned on. The LiveData class automatically notifies the UI of updates when the user's behavior changes.

2. Terminate and start video buffering. Licecycle-aware buffers as soon as possible before starting playback, and terminates buffering when destroyed.

3. Start and stop the network connection. The application will automatically connect to the network or disconnect when it is in the foreground or background.

4. Pause and play animation. The app automatically plays or pauses when it is in the foreground.

stop event processing

When Lifecycle belongs to AppCompatActivity or Fragment, its state CREATE and ON_STOP events are dispatched when onSaveInstanceState() of APPCompatActivity or Fragment is called.

Before ON_START is called, the state of Fragment or AppCompatActivity will be saved in onSaveInstanceState().

PS: FragmentManger will throw an exception if the state of the UI is saved.

LiveData prevents this edge case by avoiding calling its observer if the observer is associated with a Lifecycle at or before STARTRD. And notify its observers before isAtLeast().

Before the beta2 version, AppCompatActivity went to the new UI after its onSaveInstanceState() and before the onStop() call, and the Lifecycle was in an uncreated state at this time. After bata2, it will check the status of Lifecycle before the event is dispatched to obtain the actual status at this time.

But there are still two problems:

1. Before API level 23 or lower, even if the Android system is overwritten by another Activity, it will still save the previous state. That is to say, onSaveinstanceState() is called and onStop() may not be called. This creates a potentially long interval where the observer still considers the Lifecycle to be active, i.e. its UI state cannot be modified.

2. As long as you use LiveData, you must use the version after beta2.


Official website address: https://developer.android.google.cn/topic/libraries/architecture/lifecycle.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325406016&siteId=291194637