Geek Culture
Published in

Geek Culture

Photo by Mark Boss on Unsplash

Lifecycle — Aware Components

Architecture components are a set of android libraries that helps your app structure in a way that is testable, reusable, maintainable.

There are few lifecycle aware android architecture components:

  1. : Helps to create, store and retrieve data and communicates with other components belonging to the same lifecycle.
  2. It’s an interface implemented by activity and fragment, to observe changes to the lifecycle of owners.
  3. : Allows observing changes in data across diff components in the same lifecycle.

View Model

ViewModel is a class that is responsible for preparing and managing data for Activities and Fragments. It also helps in communication between views.

It is the backbone of MVVM architecture. A ViewModel is always created with a scope and will be retained as long as the scope is alive. For example, we bind ViewModel scope with activity then until the activity is running we can change data and get updates of data.

It exposes data using LiveData or DataBinding.

MVVM architecture’s main players are Views, ViewModel, and DataModel. Activity and Fragments are views, they should contain view hierarchy.
Data manipulation, business logic, data fetch from server, database operation should never happen in the view layer. For this work we have ViewModel. It notifies views about diff events.

This is how we define ViewModel in our view class:

UserModel userModel = new ViewModelProvider(this).get(UserModel.class);

this refers to an instance of lifecycleOwner . That means ViewModel will be alive until lifecycleOwner is alive. That means when configuration changes happen like screen rotation, ViewModel will remain unaffected.

Let’s see the following diagram for lifecycle:

Source @https://developer.android.com/codelabs/android-lifecycles/img/1d42e8efcb42ff58.png

As you can see from the diagram when the screen is rotated activity and fragment instance is destroyed but ViewModel’s not.

:

Now when you rotate the device, it doesn’t save its state, and it losses the editText’s content.

Now do the same using ViewModel.

Now rotate the screen and you will see the data is preserved and there is no glitch in retaining data. So ViewModel helps us to handle configuration changes.

ViewModel is a good choice for storing and managing UI-related data. It allows quick access to data and helps you avoid prefetching data from the network or database when configuration changes happen like scree rotation and resizing of the app. ViewModel retains data. in memory which means it is. easy to access them.

Unlike saved instance states, ViewModels are destroyed during a system-initiated process death. This is why you should use ViewModel objects in combination with onSaveInstanceState() (or some other disk persistence), stashing identifiers in saved instance state to help view models reload the data after system death.

Use saved instance state as a backup for system-initiated process death.

Commonly, we want to share data between fragments. FOr example normal list of songs and then a detail or play view of that selected song. We can achieve that by view the model using their activity scope.

private val model: SharedViewModel by activityViewModels()

By this approach, both fragments are independent of each other. And independently using a shared ViewModel.

LiveData

LiveData is a data holder class that can be observed within a given lifecycle.

The observer will be notified about the modification of wrapped data inside livedata class.

An observer added with a Lifecycle will be automatically removed if the corresponding Lifecycle moves to Lifecycle.State.DESTROYED state.

This class is designed to hold individual data fields of ViewModel, but can also be used for sharing data between different modules in your application in a decoupled fashion.

See more here: https://developer.android.com/reference/androidx/lifecycle/LiveData

Let’s understand it with an example of the Sleep tracker in HealthifyMe app:

In the red box, we have sleep goal(8h), and how much the user achieved (4h).

: Define LiveData object to store data and a method to observe that data in View class.

private val sleepGoalFetchedLiveData = MutableLiveData<SleepGoalData>()fun getSleepGoal(): LiveData<SleepGoalData> = sleepGoalFetchedLiveData

: Fetch data through API call in ViewModel class, and in onSuccess() save tha data in live Data object using sleepGoalFetchedLiveData.value = t

Define viewModel object in activity. this refers to an instance of lifecycleOwner .

private val sleepGoalViewModel: SleepGoalViewModel by lazy ViewModelProviders.of(this).get(SleepGoalViewModel::class.java)

We are observing Data changes in activity so activity will be notified when live data has been set.

getSleepGoal().observe(context, NonNullObserver<SleepGoalData> 
)

SleepGoalData class will contain sleep time and wake-up time. The goal will be the diff between these values.

var hourDiff = set(getGoalHourAndMinuteDifference(sleepTime.get(), wakeTime.get()))

Using the above code we will get our sleep goal and we will set UI.

Using the above example we can see how viewModel has been used to make API calls and data storing using live data and get the update inside our activity and fragment.

Now suppose the user wants to update the sleep goal. He will click on the edit button which was inside the red box of the above screenshot. User will enter in below Screen which is SleepGoalFragment.

Now because lifecycle is bound to activity lifeCycle and fragment is part of an activity, it will listen to all the changes happening in activity and vice versa.

Users can edit sleep time and wake time. Once after editing user click on the done button, we call saveSleepGoal API from SleepGoalViewModel.

Define viewModel object with activity lifecycle.

private val sleepGoalViewModel: SleepGoalViewModel by lazy ViewModelProviders.of(requireActivity()).get(SleepGoalViewModel::class.java)

Now on the done button click call saveGoal method of ViewModel.

btn_done.setOnClickListener sleepGoalViewModel.checkAndSaveGoal()

Call API to save data and set updated values in live data.

Because liveData is observed into activity and ViewModel lifecycle is bound to activity, even after fragment is closed, the activity will be notified for updated value and you will get. a callback inside getSleepGoal().

getSleepGoal().observe(context, NonNullObserver<SleepGoalData> 
)

From the above example, we understood how liveData will help in data transition.

LifecycleOwner

It is an interface that is used by any class that has an android lifecycle. Both ViewModel and LiveData can bind to the lifecycle owner.

Many Android components and libraries require to subscribe, initialize, unsubscribe and stop the components. Failing to do that can lead to a memory leak.

Step 1: Implement LifecycleObserver to make lifeCycle aware component.

The listener will start observing as soon as the lifecycle owner is created and will stop once the lifecycle owner is destroyed. Now activity. doesn’t need to. handle all the state it will be done by life cycle owner once it is added.

You can query the current lifecycle state inside your LifecycleOwner such as activity using getLifecycle().getCurrentState()

Conclusion

As many actions in Android applications are lifecycle driven, using lifecycle-aware components that react to lifecycle status changes to perform actions helps produce better-organized, decoupled, and light-weight components, which in turn goes a long way to building a more maintainable and testable codebase.

Thank you for reading. 👏 I hope you’ve found this article helpful. Your claps are really appreciated to help others find this article 😃 .

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store