HomeAndroidExercise and View Mannequin Lifecycles Demo App

Exercise and View Mannequin Lifecycles Demo App


The app has 2 screens (First Display and Second Display) carried out utilizing easy compose navigation.

Navigating between screens has no affect on the exercise life cycles. Nonetheless, it could affect View Mannequin lifecycle rely upon the place you instantiate the ViewModel.

Let’s first have a look at exercise lifecycle first.

Implement DefaultLifecycleObserver

That is the official exercise lifecycle diagram, indicating when these lifecycle occasion callbacks are known as. For instance, earlier than exercise goes into CREATED state, onCreate() occasion callback known as. This is applicable to the remainder of the lifecycle states.

Please be aware that onCreate() and the remainder are lifecycle occasions and never lifecycle states.

To be able to exhibit the exercise lifecycle, it is advisable to implement DefaultLifecycleObserver interface. Then, you override all of the capabilities and print out the completely different lifecycle states.

class MyLifeCycleObserver(personal val identify: String) : DefaultLifecycleObserver {

    personal val tag = "LifeCycleDebug"

    override enjoyable onCreate(proprietor: LifecycleOwner) {
        Log.d(tag, "$identify: onCreate()")
    }

    override enjoyable onStart(proprietor: LifecycleOwner) {
        Log.d(tag, "$identify: onStart()")
    }

    override enjoyable onResume(proprietor: LifecycleOwner) {
        Log.d(tag, "$identify: onResume()")
    }

    override enjoyable onPause(proprietor: LifecycleOwner) {
        Log.d(tag, "$identify: onPause()")
    }

    override enjoyable onStop(proprietor: LifecycleOwner) {
        Log.d(tag, "$identify: onStop()")
    }

    override enjoyable onDestroy(proprietor: LifecycleOwner) {
        Log.d(tag, "$identify: onDestroy()")
    }
}

In exercise, you register this lifecycle observer in onCreate() perform.

class MainActivity : ComponentActivity() {

    override enjoyable onCreate(savedInstanceState: Bundle?) {

        tremendous.onCreate(savedInstanceState)

        val observer = MyLifeCycleObserver(MainActivity::class.simpleName!!)
        lifecycle.addObserver(observer)

        
        }
    }
}

For some causes, the onRestart() callback just isn’t out there in DefaultLifecycleObserver. So it is advisable to additionally override the onRestart() in your exercise.

class MainActivity : ComponentActivity() {
    

    override enjoyable onRestart() {
        tremendous.onRestart()

        Log.d(
            "LifeCycleDebug",
            "${MainActivity::class.simpleName!!}: onRestart()")
    }
}

Simulate Exercise Loses Focus

To be able to exhibit the present exercise lifecycle is paused (loses focus), the present exercise wants to enter background, however nonetheless seen. To do this, you begin a second exercise with clear background.

First, you create this Loses Focus button to start out the second exercise.

val context = LocalContext.present

DefaultButton(
    textual content = "Loses Focus",
    onClick = {
        context.startActivity(Intent(context, SecondActivity::class.java))
    }
)

In AndroidManifest.xml, add the second exercise with android:theme="@android:type/Theme.Translucent":

<exercise
    android:identify="com.instance.understandlifecyclesdemo.ui.SecondActivity"
    android:exported="true"
    android:theme="@android:type/Theme.Translucent">
</exercise>

When the button is clicked, the present exercise loses focus. Thus, it goes into PAUSED state.

Exercise Lifecycle Abstract

Attempt to mess around with completely different eventualities and examine the output from Logcat.

Right here is the abstract of all of the completely different eventualities.

State of affairs Exercise Lifecycle Occasion Callbacks
Begins up onCreate() → onStart() → onResume()
Navigate to completely different screens No transition
Begins second clear exercise onPause()
Press again button (from the clear exercise) onResume()
Rotate display onPause() → onStop() → onDestroy() → onCreate() → onStart() → onResume()
Press dwelling button onPause() → onStop()
Press sq. button and choose the app onRestart() → onStart() → onResume()
Shut down (press again button) onPause() → onStop() → onDestroy()
Simulate course of demise (press dwelling button, kill the method manually) onPause() → onStop()

Please be aware that in course of demise, onDestroy() occasion callback just isn’t fired.

To simulate course of demise, you first must press the house button to maneuver the exercise into background. After that, you kill the method manually. The best option to kill the method is utilizing the cease button in Logcat.

Activity_and_ViewModel_Lifecycle_Demo_App_01.png

[Updated – Oct 15, 2022]: The above technique does NOT work anymore on Android Studio Dolphin model. See the next article for extra particulars.

Extra detailed descriptions on every lifecycle state under:

Exercise Lifecycle State Description
CREATED Exercise is created and NOT seen
STARTED Exercise is seen at background
RESUMED Exercise is seen at foreground
DESTROYED Exercise is exited / shut down by person

Please be aware that there aren’t any Paused, Stopped and Restarted lifecycle states which I discover it a bit complicated. See diagram under.

ON_PAUSE occasion sends the lifecyle state to STARTED. ON_STOP occasion sends the lifecyle state to CREATED.

Lifecycle Occasion Lifecycle State Description
ON_PAUSE STARTED Exercise is paused and visual, nonetheless in foreground
ON_STOP CREATED Exercise is NOT seen, transfer from foreground to background
N/A RESTARTED Intermediate state between Stopped and Began phases

For full documentation, you possibly can confer with this official documentation right here.

Now, let’s take a look at the View Mannequin lifecycle.

When ViewModel is Created and Destroyed?

There are solely 2 lifecycle phases in View Mannequin:

  • ViewModel is created. That’s when ViewModel constructor known as.
  • ViewModel is destroyed. That’s when ViewModel.onCleared() known as.
class MainViewModel(personal val identify: String) : ViewModel() {  

    personal val tag = "LifeCycleDebug"  

    init {  
        Log.d(tag, "${identify}ViewModel: onCreated()")  
    }  

    override enjoyable onCleared() {  
        tremendous.onCleared()  

        Log.d(tag, "${identify}ViewModel: onCleared()")  
    }  
}

Since MainViewModel takes in constructor parameter (to distinguish the ViewModel situations), it is advisable to create the MainViewModelFactory

class MainViewModelFactory(personal val identify: String)  
    : ViewModelProvider.NewInstanceFactory() {  

    override enjoyable <T : ViewModel> create(modelClass: Class<T>): T {  

        if (modelClass.isAssignableFrom(MainViewModel::class.java))  
            return MainViewModel(identify) as T  

    throw IllegalArgumentException("Unknown ViewModel class")  
    }  
}

To be able to exhibit this View Mannequin lifecycle, you create the ViewModel in 3 completely different locations:

Create ViewModel in MainScreen()

@Composable  
personal enjoyable MainScreen() {  
    
    val viewModel: MainViewModel = viewModel(
        manufacturing facility = MainViewModelFactory("MainScreen"))  
    
}

Create ViewModel in FirstScreen()

@Composable  
enjoyable FirstScreen(  
    navigateToSecondScreen: () -> Unit  
) {  
    
  val viewModel: MainViewModel = viewModel(  
        manufacturing facility = MainViewModelFactory("FirstScreen"))
  
}

Create ViewModel in SecondScreen()

@Composable  
enjoyable SecondScreen(  
    popBackStack: () -> Unit,  
) {  
    
  val viewModel: MainViewModel = viewModel(  
        manufacturing facility = MainViewModelFactory("SecondScreen"))
}

View Mannequin Lifecycle Abstract

Let’s examine the Logcat and see what occurs.

State of affairs View Mannequin Lifecycle State
Begins up After exercise is resumed, important and first display view fashions are created
Navigate to Second Display Second display view mannequin is created
Pop again to first Display Second display view mannequin is destroyed
Rotate the display No affect to view mannequin lifecycle
Press again and exit the app After exercise is destroyed, important and first display view fashions are destroyed

ViewModelStoreOwner determines the view mannequin lifecycle. It’s set to LocalViewModelStoreOwner.present depends upon the place you name the viewModel() composable perform.

In MainScreen(), earlier than the navigation graph is construct, the ViewModelStoreOwner belongs to the exercise. In FirstScreen() and SecondScreen(), compose navigation creates a brand new ViewModelStoreOwner for every display vacation spot. Nonetheless, since First Display is the foundation/begin vacation spot, its lifecycle very a lot the identical because the Essential Display view mannequin, which is tied to the exercise lifecycle.

So, after the exercise is resumed, each Essential and First Display view fashions are created. Second Display view mannequin is created when it’s pushed to the stack. When it pops from stack, it’s then destroyed.

When the app is shutdown, exercise is destroyed. After that, Essential and First Display view fashions are destroyed. The diagram under summarizes what occurs.

Activity_and_ViewModel_Lifecycle_Demo_App_02.png

Conclusion

Exercise lifecycle is widespread and effectively documented. Nonetheless, it isn’t utterly clear on view mannequin lifecycle, particularly when it will likely be destroyed.

Earlier than I ran the check on this straightforward app, I had an impression that when the composable display is gone off-screen, its view mannequin is destroyed. I assumed the view mannequin lifecycle is tied to composable display.

Properly, this isn’t the case. It’s based mostly on the again stack from the navigation. When the display is added into the again stack, its view mannequin is created. When it’s faraway from the again stack, its view mannequin is destroyed.

Supply Code

GitHub Repository: Demo_UnderstandLifecycles

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments