LiveData and LifeCycle Component in Android Architecture

Sharing is caring!

In this tutorial, we will learn the new architecture component LiveData and LifeCycle in detail. In my last tutorial, we had familiar with new Dagger2 integration with android architecture component. I would be recommended to check this post that will help you to understand the New Dagger2 dependency injection concept. Here is the post detail New Dagger2 dependency injection integration with android architecture component. If you are curious to know the old Deagger2 implementation of MVP design pattern then please check this post.

LiveData is one of the newly introduced architecture components. LiveData is an observable data holder. This allows the components of your app to be able to observe LiveData objects for changes happened.  LiveData is a leverages reactive programming which helps us manipulate data easily. It shares some similarities with Stream in Java 8 and Observable or Flowable in RxJava or RxJava2. However, LiveData has an advantage is that it is lifecycle-aware specific for Android. So, it works closely with LifeCycle components.

LiveData is a variant of the original observer pattern, with the addition of active/inactive transitions. For example, we can say in a network connectivity, Live data is observing the connection between active and inactive state automatically and we can do the respective actions in this scope.  Let’s see by an example but before we need to add a relevant dependency in your build.gradle file.

archVersion = '1.0.0-alpha1'

archRuntime = "android.arch.lifecycle:runtime:$archVersion"
archExtension = "android.arch.lifecycle:extensions:$archVersion"
archCompiler = "android.arch.lifecycle:compiler:$archVersion"

Here is the network connectivity Live data example.

public class NetworkLiveData extends LiveData<Network>{

    private ConnectivityManager connectivityManager;

    private ConnectivityManager.NetworkCallback listener = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network){
            //this part runs on background thread so use postValue
            postValue(network);
        }
        @Override
        public void onLost(Network network){
            postValue(network);
        }
    };

    public NetworkLiveData(Context context) {
        //get connectivity system service
        connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    @Override
    protected void onActive() {
        //if active observers exist, add netwrok callback from connectivity manager
        connectivityManager.registerDefaultNetworkCallback(listener);
    }

    @Override
    protected void onInactive() {
        //no active observers exist, remove netwrok callback from connectivity manager
        connectivityManager.unregisterNetworkCallback(listener);
    }

}

Here NetworkLiveData is ready, now we need to observe on network change. Live data is only delivered the change update if any observer is listening to this change else it will not. In this case, memory leak chance will be removed.

public class MovieListFragment extends LifecycleFragment{

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 
              Bundle savedInstanceState) {
        
        LiveData<Network> networkData = new NetworkLiveData(getActivity());
        networkData.observe(this, new Observer<Network>() {
            @Override
            public void onChanged(@Nullable Network network) {
                Toast.makeText(getActivity(), " " + network.describeContents(), Toast.LENGTH_LONG).show();
            }
        });
        return mView;
    }
}

LifeCycle addresses the Android lifecycle problems ineffective and easy ways. It has two main parts. LifecycleOwner exposes its state changes or it is an interface for components having Lifecycle (such as Activities and Fragments)., and LifecycleObserver listens to these changes to make appropriate steps. LifecycleObserver subscribes to LifecycleOwner’s lifecycle state changes.

It does not have to rely on Activity or fragment’s onStart() or onStop()lifecycle callback to initialize and stop it. Here we can take an example of Location update.

public class LocationProvider implements LifecycleObserver {
    private final Context context;
    private final Lifecycle lifecycle;
    private final LocationListener locationListener;
 
    private FusedLocationProviderClient fusedLocationProviderClient = null;
 
    public LocationProvider(@NonNull Context context, Lifecycle lifecycle, @NonNull LocationListener listener) {
        this.context = context;
        this.lifecycle = lifecycle;
        this.locationListener = listener;
        lifecycle.addObserver(this);
    }
 
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void registerForLocationUpdates() {
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        FusedLocationProviderClient locationProviderClient = getFusedLocationProviderClient();
        LocationRequest locationRequest = LocationRequest.create();
        Looper looper = Looper.myLooper();
        locationProviderClient.requestLocationUpdates(locationRequest, locationCallback, looper);
    }
 
    @NonNull
    private FusedLocationProviderClient getFusedLocationProviderClient() {
        if (fusedLocationProviderClient == null) {
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
        }
        return fusedLocationProviderClient;
    }
 
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void unregisterForLocationUpdates() {
        if (fusedLocationProviderClient != null) {
            fusedLocationProviderClient.removeLocationUpdates(locationCallback);
        }
    }
 
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void unregisterObserver() {
        lifecycle.removeObserver(this);
    }
 
    private LocationCallback locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            super.onLocationResult(locationResult);
            Location lastLocation = locationResult.getLastLocation();
            double latitude = lastLocation.getLatitude();
            double longitude = lastLocation.getLongitude();
            float accuracy = lastLocation.getAccuracy();
            CommonLocation location = new CommonLocation(latitude, longitude, accuracy);
            locationListener.updateLocation(location);
        }
    };
 
}

And we can call this in Fragment.

public class LocationFragment extends LifecycleFragment  {
 
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        new LocationProvider(getContext(), getLifecycle(), this);
    }
 }

Using LiveData provides the following advantages:

Ensures your UI matches your data state
LiveData follows the observer pattern. LiveData notifies Observer objects when the lifecycle state changes. You can consolidate your code to update the UI in these Observer objects. Instead of updating the UI every time the app data changes, your observer can update the UI every time there’s a change.

No memory leaks
Observers are bound to Lifecycle objects and clean up after themselves when their associated lifecycle is destroyed.
No crashes due to stopped activities, If the observer’s lifecycle is inactive, such as in the case of an activity in the back stack, then it doesn’t receive any LiveData events.

No more manual lifecycle handling
UI components just observe relevant data and don’t stop or resume observation. LiveData automatically manages all of this since it’s aware of the relevant lifecycle status changes while observing.

Always up to date data
If a lifecycle becomes inactive, it receives the latest data upon becoming active again. For example, an activity that was in the background receives the latest data right after it returns to the foreground. Proper configuration changes If an activity or fragment is recreated due to a configuration change, like device rotation, it immediately receives the latest available data.

Wrapping up: LiveData is something like Rx Observable that reacts if any change happened in Object. We can use the LiveData in android application development in multiple places like Fetching data by using Retrofit or Database.  Here is the Github link for an Android Architecture example of Retrofit and Database LiveData with LifeCyle.

Please do subscribe email to get all newsletters of this blog and if you feel that this post will help you to better understand then do not forget to subscribe, share and comment below. Ok, then I will see you in my next tutorial till then enjoy your life and happy coding 🙂

0 0 votes
Article Rating
LiveData and LifeCycle Component in Android Architecture
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Scroll to top
0
Would love your thoughts, please comment.x
()
x