Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The A, B and C of Lifecycle Components

The A, B and C of Lifecycle Components

[Droidcon Berlin '18] If you've been developing Android applications for a while now, you know the pain of handling the lifecycle just right. It’s a pain-point that has existed since the advent of Android, up until recently when Google released Architecture components. As an Android developer you are bugged by handling activity/fragment lifecycle and flow of data in tandem to the lifecycle changes day in and out. Making your code aware about the lifecycle of the process/activity/fragment makes you more confident as a developer and enables faster development. This session would enable you to understand Lifecycle components (ProcessLifecycleOwner, LifecycleOwner, LifecycleObserver) and how they are leveraged in other architecture components like LiveData and ViewModel.

Google Slides Link: https://docs.google.com/presentation/d/1b8mEH9hwwBxUiUk4xxib15sL7UIAYrP2TiSDXY9ZGS4

Nishant Srivastava

June 26, 2018
Tweet

More Decks by Nishant Srivastava

Other Decks in Technology

Transcript

  1. The Challenge Android activity lifecycle - Many states - Repeats

    on configuration changes @nisrulz #DCBERLIN18
  2. The Challenge Android activity lifecycle - Many states - Repeats

    on configuration changes Not to forget... @nisrulz #DCBERLIN18
  3. Lifecycle Components Series of classes designed to help deal with

    lifecycles in a more consistent fashion. @nisrulz #DCBERLIN18
  4. Lifecycle Components Series of classes designed to help deal with

    lifecycles in a more consistent fashion. - Lifecycle - LifecycleOwner - LifecycleObserver @nisrulz #DCBERLIN18
  5. Lifecycle Series of states an object can be in. For

    Android: Object that defines Android lifecycle states. i.e. Activity & Fragment @nisrulz #DCBERLIN18
  6. Lifecycle dependencies { def lifecycle_version = "1.1.1" // Support library

    already depends on this (since v26.1.0) // Both AppCompatActivity & Support Fragment implement // LifecycleOwner interface. // Lifecycles only implementation "android.arch.lifecycle:runtime:$lifecycle_version" ... } @nisrulz #DCBERLIN18
  7. Lifecycle // Source code public abstract class Lifecycle { //

    Adds a LifecycleObserver addObserver(@NonNull LifecycleObserver observer) // Removes the given observer from the observers list removeObserver(@NonNull LifecycleObserver observer) // Current state of the Lifecycle getCurrentState() // Compares the lifecycle states isAtLeast(@NonNull State state) ... } @nisrulz #DCBERLIN18
  8. Lifecycle // Source code public abstract class Lifecycle { //

    Adds a LifecycleObserver addObserver(@NonNull LifecycleObserver observer) // Removes the given observer from the observers list removeObserver(@NonNull LifecycleObserver observer) // Current state of the Lifecycle getCurrentState() // Compares the lifecycle states isAtLeast(@NonNull State state) ... } @nisrulz #DCBERLIN18
  9. Lifecycle // Source code public abstract class Lifecycle { //

    Adds a LifecycleObserver addObserver(@NonNull LifecycleObserver observer) // Removes the given observer from the observers list removeObserver(@NonNull LifecycleObserver observer) // Current state of the Lifecycle getCurrentState() // Compares the lifecycle states isAtLeast(@NonNull State state) ... } @nisrulz #DCBERLIN18
  10. LifecycleOwner Interface that goes through Android Lifecycle. // Source code

    public interface LifecycleOwner { // Returns the Lifecycle of the provider. @NonNull Lifecycle getLifecycle(); } @nisrulz #DCBERLIN18
  11. LifecycleOwner class MainActivity : AppCompatActivity() { // Missing myLifecycleObserver override

    fun onResume() { // Add lifecycle observer lifecycle.addObserver(myLifecycleObserver) } override fun onStop() { // Remove lifecycle observer lifecycle.removeObserver(myLifecycleObserver) } } @nisrulz #DCBERLIN18
  12. LifecycleOwner Fun Fact: Activities & fragments are not the only

    things with lifecycle by default @nisrulz #DCBERLIN18
  13. LifecycleOwner Fun Fact: Activities & fragments are not the only

    things with lifecycle by default You also have - LifecycleService - ProcessLifecycleOwner @nisrulz #DCBERLIN18
  14. LifecycleService A service that is also a LifecycleOwner // Source

    code public class LifecycleService extends Service implements LifecycleOwner { ... } @nisrulz #DCBERLIN18
  15. ProcessLifecycleOwner - Class that tracks the lifecycle of - whole

    application process or - all the activities combined @nisrulz #DCBERLIN18
  16. ProcessLifecycleOwner - Class that tracks the lifecycle of - whole

    application process or - all the activities combined - Useful for reacting to app coming to foreground or going to background @nisrulz #DCBERLIN18
  17. ProcessLifecycleOwner dependencies { def lifecycle_version = "1.1.1" // For ProcessLifecycleOwner

    implementation "android.arch.lifecycle:extensions:$lifecycle_version" ... } @nisrulz #DCBERLIN18
  18. ProcessLifecycleOwner ON_CREATE (Only 1 time) ON_START & ON_RESUME (First Activity

    pass) ON_PAUSE & ON_STOP ON_DESTROY @nisrulz #DCBERLIN18
  19. ProcessLifecycleOwner ON_CREATE (Only 1 time) ON_START & ON_RESUME (First Activity

    pass) ON_PAUSE & ON_STOP (after 700ms delay) ON_DESTROY @nisrulz #DCBERLIN18
  20. ProcessLifecycleOwner ON_CREATE (Only 1 time) ON_START & ON_RESUME (First Activity

    pass) ON_PAUSE & ON_STOP (after 700ms delay) ON_DESTROY @nisrulz #DCBERLIN18
  21. ProcessLifecycleOwner ON_CREATE (Only 1 time) ON_START & ON_RESUME (First Activity

    pass) ON_PAUSE & ON_STOP (after 700ms delay) ON_DESTROY @nisrulz #DCBERLIN18
  22. ProcessLifecycleOwner ON_PAUSE & ON_STOP (after 700ms delay) // Source code

    public class ProcessLifecycleOwner implements LifecycleOwner { static final long TIMEOUT_MS = 700; //mls ... } @nisrulz #DCBERLIN18
  23. ProcessLifecycleOwner Guarantee that ProcessLifecycleOwner won’t send any events if activities

    are - Destroyed - Recreated due to configuration change @nisrulz #DCBERLIN18
  24. ProcessLifecycleOwner // Source code // Internal class to initialize Lifecycles.

    public class ProcessLifecycleOwnerInitializer extends ContentProvider { @Override public boolean onCreate() { ... ProcessLifecycleOwner.init(getContext()); return true; } ... } @nisrulz #DCBERLIN18
  25. ProcessLifecycleOwner Side-effect: Inits ProcessLifecycleOwner even if your app does not

    use it! Why? So that ProcessLifecycleOwner can be invoked as soon as process starts @nisrulz #DCBERLIN18
  26. Application.ActivityLifecycleCallback // Source code public interface ActivityLifecycleCallbacks { void onActivityCreated(Activity

    var1, Bundle var2); ... void onActivitySaveInstanceState(Activity var1, Bundle var2); void onActivityDestroyed(Activity var1); } @nisrulz #DCBERLIN18
  27. ProcessLifecycleOwner // Source code public class ProcessLifecycleOwner implements LifecycleOwner {

    ... void attach(Context context) { ... Application app = (Application) context.getApplicationContext(); app.registerActivityLifecycleCallbacks (new EmptyActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { .. } ... }); } } @nisrulz #DCBERLIN18
  28. ProcessLifecycleOwner // Source code public class ProcessLifecycleOwner implements LifecycleOwner {

    ... void attach(Context context) { ... Application app = (Application) context.getApplicationContext(); app.registerActivityLifecycleCallbacks (new EmptyActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { .. } ... }); } } @nisrulz #DCBERLIN18
  29. ProcessLifecycleOwner // Source code public class ProcessLifecycleOwner implements LifecycleOwner {

    ... void attach(Context context) { ... Application app = (Application) context.getApplicationContext(); app.registerActivityLifecycleCallbacks (new EmptyActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { .. } ... }); } } @nisrulz #DCBERLIN18
  30. ProcessLifecycleOwner // Source code class EmptyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { @Override

    public void onActivityCreated(Activity activity, Bundle savedInstanceState) { //Empty method body } ... } @nisrulz #DCBERLIN18
  31. ProcessLifecycleOwner // Source code class EmptyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { @Override

    public void onActivityCreated(Activity activity, Bundle savedInstanceState) { //Empty method body } ... } @nisrulz #DCBERLIN18
  32. LifecycleRegistry Implementation of Lifecycle that can handle multiple observers //

    Source code public class LifecycleRegistry extends Lifecycle { ... } @nisrulz #DCBERLIN18
  33. LifecycleRegistry Implementation of Lifecycle that can handle multiple observers //

    Source code public class LifecycleRegistry extends Lifecycle { ... } However, you need to dispatch the events yourself. @nisrulz #DCBERLIN18
  34. LifecycleRegistry class MyLifecycleOwner : LifecycleOwner { private var registry: LifecycleRegistry

    = LifecycleRegistry(this) init { registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) } override fun getLifecycle(): Lifecycle = registry fun startListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_START) } fun stopListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) } } @nisrulz #DCBERLIN18
  35. LifecycleRegistry class MyLifecycleOwner : LifecycleOwner { private var registry: LifecycleRegistry

    = LifecycleRegistry(this) init { registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) } override fun getLifecycle(): Lifecycle = registry fun startListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_START) } fun stopListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) } } @nisrulz #DCBERLIN18
  36. LifecycleRegistry class MyLifecycleOwner : LifecycleOwner { private var registry: LifecycleRegistry

    = LifecycleRegistry(this) init { registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) } override fun getLifecycle(): Lifecycle = registry fun startListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_START) } fun stopListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) } } @nisrulz #DCBERLIN18
  37. LifecycleRegistry class MyLifecycleOwner : LifecycleOwner { private var registry: LifecycleRegistry

    = LifecycleRegistry(this) init { registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) } override fun getLifecycle(): Lifecycle = registry fun startListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_START) } fun stopListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) } } @nisrulz #DCBERLIN18
  38. LifecycleRegistry class MyLifecycleOwner : LifecycleOwner { private var registry: LifecycleRegistry

    = LifecycleRegistry(this) init { registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) } override fun getLifecycle(): Lifecycle = registry fun startListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_START) } fun stopListening() { registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) } } @nisrulz #DCBERLIN18
  39. LifecycleRegistry val myLifecycleOwner = MyLifecycleOwner() // Missing myLifecycleObserver // Add

    lifecycle observer myLifecycleOwner.lifecycle.addObserver(myLifecycleObserver) // Remove lifecycle observer myLifecycleOwner.lifecycle.removeObserver(myLifecycleObserver) @nisrulz #DCBERLIN18
  40. LifecycleObserver An interface for observing a Lifecycle // Source code

    public interface LifecycleObserver { // Empty } @nisrulz #DCBERLIN18
  41. LifecycleObserver dependencies { def lifecycle_version = "1.1.1" // For Annotation

    Support annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" ... } @nisrulz #DCBERLIN18
  42. LifecycleObserver class MyLifecycleObserver : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun init() {}

    @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onStart() {} ... @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun cleanup() {} } @nisrulz #DCBERLIN18
  43. LifecycleObserver val myLifecycleOwner = MyLifecycleOwner() // Add lifecycle observer myLifecycleOwner.lifecycle.addObserver(myLifecycleObserver)

    // Remove lifecycle observer myLifecycleOwner.lifecycle.removeObserver(myLifecycleObserver) @nisrulz #DCBERLIN18
  44. LifecycleObserver val myLifecycleOwner = MyLifecycleOwner() val myLifecycleObserver = MyLifecycleObserver() //

    Add lifecycle observer myLifecycleOwner.lifecycle.addObserver(myLifecycleObserver) // Remove lifecycle observer myLifecycleOwner.lifecycle.removeObserver(myLifecycleObserver) @nisrulz #DCBERLIN18
  45. LifecycleObserver val myLifecycleOwner = MyLifecycleOwner() val myLifecycleObserver = MyLifecycleObserver() //

    Add lifecycle observer myLifecycleOwner.lifecycle.addObserver(myLifecycleObserver) // Remove lifecycle observer myLifecycleOwner.lifecycle.removeObserver(myLifecycleObserver) @nisrulz #DCBERLIN18
  46. DefaultLifecycleObserver android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }

    } dependencies { def lifecycle_version = "1.1.1" // For DefaultLifecycleObserver implementation "android.arch.lifecycle:common-java8:$lifecycle_version" ... } @nisrulz #DCBERLIN18
  47. DefaultLifecycleObserver // Source code public interface DefaultLifecycleObserver extends FullLifecycleObserver {

    @Override default void onCreate(@NonNull LifecycleOwner owner) { ... } ... @Override default void onDestroy(@NonNull LifecycleOwner owner) { ... } } @nisrulz #DCBERLIN18
  48. DefaultLifecycleObserver // Source code interface FullLifecycleObserver extends LifecycleObserver { void

    onCreate(LifecycleOwner owner); void onStart(LifecycleOwner owner); ... void onDestroy(LifecycleOwner owner); } @nisrulz #DCBERLIN18
  49. LiveData A lifecycle aware base class for encapsulating loading data

    Lightweight implementation of Observer pattern @nisrulz #DCBERLIN18
  50. LiveData dependencies { def lifecycle_version = "1.1.1" // For LiveData

    implementation "android.arch.lifecycle:livedata:$lifecycle_version" ... } @nisrulz #DCBERLIN18
  51. LiveData // Source Code public abstract class LiveData<T> { ...

    protected void postValue(T value) {...} ... @MainThread protected void setValue(T value) {...} ... protected void onActive() {...} protected void onInactive() {...} } @nisrulz #DCBERLIN18
  52. LiveData // Source Code public abstract class LiveData<T> { ...

    protected void postValue(T value) {...} // Sets the value async ... @MainThread protected void setValue(T value) {...} ... protected void onActive() {...} protected void onInactive() {...} } @nisrulz #DCBERLIN18
  53. LiveData // Source Code public abstract class LiveData<T> { ...

    protected void postValue(T value) {...} // Sets the value async ... @MainThread protected void setValue(T value) {...} // Sets the value sync ... protected void onActive() {...} protected void onInactive() {...} } @nisrulz #DCBERLIN18
  54. LiveData // Source Code public abstract class LiveData<T> { ...

    protected void postValue(T value) {...} // Sets the value async ... @MainThread protected void setValue(T value) {...} // Sets the value sync ... protected void onActive() {...} // Has active observers i.e in Start/Resume state protected void onInactive() {...} } @nisrulz #DCBERLIN18
  55. LiveData // Source Code public abstract class LiveData<T> { ...

    protected void postValue(T value) {...} // Sets the value async ... @MainThread protected void setValue(T value) {...} // Sets the value sync ... protected void onActive() {...} // Has active observers i.e in Start/Resume state protected void onInactive() {...} // Has 0 active observers } @nisrulz #DCBERLIN18
  56. LiveData class MySensorLiveData(context: Context?) : LiveData<Float>() { val sensorManager: SensorManager?

    = context? .getSystemService(Service.SENSOR_SERVICE) as SensorManager val sensorListener: SensorEventListener = object : SensorEventListener { override fun onSensorChanged(event: SensorEvent?) { // Set Value setValue(event?.values?.get(0)) } ... } } @nisrulz #DCBERLIN18
  57. LiveData class MySensorLiveData(context: Context?) : LiveData<Float>() { val sensorManager: SensorManager?

    = context? .getSystemService(Service.SENSOR_SERVICE) as SensorManager val sensorListener: SensorEventListener = object : SensorEventListener { override fun onSensorChanged(event: SensorEvent?) { // Set Value setValue(event?.values?.get(0)) } ... } } @nisrulz #DCBERLIN18
  58. LiveData class MySensorLiveData(context: Context?) : LiveData<Float>() { ... override fun

    onActive() { ... sensorManager?.registerListener(sensorListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST) } override fun onInactive() { ... sensorManager.unregisterListener(sensorListener) } } @nisrulz #DCBERLIN18
  59. LiveData class MySensorLiveData(context: Context?) : LiveData<Float>() { ... override fun

    onActive() { ... sensorManager?.registerListener(sensorListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST) } override fun onInactive() { ... sensorManager.unregisterListener(sensorListener) } } @nisrulz #DCBERLIN18
  60. LiveData val mySensorLiveData = MySensorLiveData(this) // Observe for values mySensorLiveData.observe(this,

    Observer<Float>{ floatVal -> // Update the UI }) @nisrulz #DCBERLIN18
  61. ViewModel - Hold & manage UI related data in Lifecycle

    conscious way - Survives configuration changes - Prevents unnecessary reloading of data @nisrulz #DCBERLIN18
  62. ViewModel dependencies { def lifecycle_version = "1.1.1" // For ViewModel

    implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" ... } @nisrulz #DCBERLIN18
  63. ViewModel // Source code public abstract class ViewModel { //

    Called when ViewModel is destroyed protected void onCleared() { } } @nisrulz #DCBERLIN18
  64. ViewModel class MyViewModel : ViewModel() { private val username =

    MutableLiveData<String>() fun initExpensiveOperation() { // expensive operation, e.g. network request username.value = "Nishant" // username.setValue(“Nishant”) } fun getUsername(): LiveData<String> { return username } } @nisrulz #DCBERLIN18
  65. ViewModel class MyViewModel : ViewModel() { private val username =

    MutableLiveData<String>() fun initExpensiveOperation() { // expensive operation, e.g. network request username.value = "Nishant" // username.setValue(“Nishant”) } fun getUsername(): LiveData<String> { return username } } @nisrulz #DCBERLIN18
  66. ViewModel class MyViewModel : ViewModel() { private val username =

    MutableLiveData<String>() fun initExpensiveOperation() { // expensive operation, e.g. network request username.value = "Nishant" // username.setValue(“Nishant”) } fun getUsername(): LiveData<String> { return username } } @nisrulz #DCBERLIN18
  67. ViewModel class MyViewModel : ViewModel() { private val username =

    MutableLiveData<String>() fun initExpensiveOperation() { // expensive operation, e.g. network request username.value = "Nishant" // username.setValue(“Nishant”) } fun getUsername(): LiveData<String> { return username } } @nisrulz #DCBERLIN18
  68. ViewModel class MyViewModel : ViewModel() { private val username =

    MutableLiveData<String>() fun initExpensiveOperation() { // expensive operation, e.g. network request username.value = "Nishant" // username.setValue(“Nishant”) } fun getUsername(): LiveData<String> { return username } } @nisrulz #DCBERLIN18
  69. ViewModel class MyViewModel : ViewModel() { private val username =

    MutableLiveData<String>() fun initExpensiveOperation() { // expensive operation, e.g. network request username.value = "Nishant" // username.setValue(“Nishant”) } fun getUsername(): LiveData<String> { return username } } @nisrulz #DCBERLIN18
  70. More Info Is your Android Library, Lifecycle-Aware? https://android.jlelse.eu/is-your-android-library-lifecycle-aware-127629d32dcc Official documentation

    about lifecycle components d.android.com/topic/libraries/architecture/lifecycle Using ProcessLifecycleOwner for libraries example https://github.com/nisrulz/android-examples/tree/develop/UsingProcessLifecycleOwnerForLibs Using Lifecycle Components for libraries example https://github.com/nisrulz/android-examples/tree/develop/LifeCycleCompForLib @nisrulz #DCBERLIN18