Android

Android Architecture Components – A walkthrough

Android architectures components is a set of libraries and guidance for modern architecture. These components can combine to create a testable, and maintainable apps. The new Architecture Components help solve some of the more difficult problems that you may have faced when building your Android applications in the past.

Android architecture components are:-

  • Handling Lifecycle
  • LiveData
  • ViewModel
  • Room
Adding Architecture Components to Your Project

first, add the Google repository to your build.gradle file

allprojects {
repositories {
jcenter()
// Add Google repository
maven { url 'https://maven.google.com' }
}
}
Handling Lifecycle

Lifecycle is a class that contains the information about the lifecycle state of an activity or a fragment and also allows other objects to observe this state.

Lifecycle Observer classes are used to observe Lifecycle object which is an attachment of Activities and Fragments, like a ViewModel or any object that implements this interface. Here the observer will receive updates about the state changes of the object that it is observing, like when an Activity is paused or when it is starting.
It can also check the current state of the observed object.

A class can monitor the component’s lifecycle status by adding annotations to its methods. addObserver() method of the lifecycle class is used to add an observer.

example:

public class ObserverClass implements LifecycleObserver {

   @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)

   public void connectListener() {  …

   }

   @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)

   public void disconnectListener() {… }}

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

LiveData is an observable data holder class which is also life cycle aware. LiveData also respects the lifecycle state of app components and prevent object leaking so that app does not consume more memory.

LiveData knows

  • When the data was changed
  • observer is active and should receive an update

LiveData is capable of removing the observer if it’s in Lifecycle.State.DESTROYED state and can avoiding memory leaks.

The advantages of using LiveData
  • No memory leaks
  • Ensures your UI matches your data state
  • No crashes due to stopped activities
  • No more manual lifecycle handling
  • Always up to date data
Work with LiveData objects
  1. Create an instance of LiveData to hold a certain type of data. This is usually done within your View Model class.
  1. Create an Observer object that defines the onChanged() method, which controls what happens when the LiveData object’s held data changes. You usually create an Observer object in a UI controller, such as an activity or fragment.
  2. Attach the Observer object to the LiveData object using the observe() method. The observe()method takes a LifecycleOwner object. This subscribes the Observer object to the LiveData object so that it is notified of changes. You usually attach the Observer object in a UI controller, such as an activity or fragment.
ViewModel

A ViewModel provides the data for a specific UI component, such as a fragment or activity, and handles the communication with the business part of data handling, such as calling other components to load the data or forwarding user modifications. The ViewModel does not know about the View and is not affected by configuration changes such as recreating an activity due to the rotation.

Implement a ViewModel

To create a view model, extend the ViewModel class.

class SampleViewModel : ViewModel() {

    private var employee: MutableLiveData<List<String>>? = null

   fun getName(): LiveData<List<String>> {

       if (employee == null) {

           employee = MutableLiveData<List<String>>()

           loadEmployeeList()

       }

       return employee!!

   }

   private fun loadEmployeeList() {

       // do async operation to fetch employeelist

   }

}

You can then access the list from an activity as follows:

class MainActivity : LifecycleActivity(){

   override fun onCreate(savedInstanceState: Bundle?) {

       super.onCreate(savedInstanceState)

       setContentView(R.layout.activity_main)

       val viewModel = ViewModelProviders.of(this)

               .get(MainActivityViewModel::class.java)

       viewModel.getName().observe(

               this, Observer {

                   employee -> info(“employee: $employee”)

               }

       )

   }

}
The lifecycle of a ViewModel
Room

Room is an SQLite object mapping library. It gives us annotations to generate boilerplate codes. The room library helps to create a cache of app’s data on a device that’s running your app.

First, Android supported SQLite; it has some drawbacks,

Necessary to write a lot of boilerplate

SQLite didn’t save POJOs (plain-old Java objects)

Didn’t check queries at compile time

Along comes Room to solve these issues! Room is an SQLite mapping library.

Advantage of Room
  • Persisting Java POJOs
  • Directly converting queries to objects
  • Checking errors at compile time
  • Producing Live Data observables from query results
  • Room is an Object Relational Mapping library with some cool Android extras.

To create a Room database, you’ll need an @Entity,@Dao,@Database.

@Entity – @Entity is used to persist, which can be any Java POJO

@Dao – @Dao is an interface to make queries and input/output operations

@Database – @Database abstract class that must extend Room Database.

            @Entity

class Employee {

            @PrimaryKey

             var id: Int = 0

            var name: String? = null

            }

           @Dao

interface EmployeeDAO {

           @Insert( onConflict = OnConflictStrategy.REPLACE )

            fun insertName(name: Employee)

           @Update( onConflict = OnConflictStrategy.REPLACE )

            fun updateName(name: Employee)
@Delete

           fun deleteName(name: Employee)

           @Query(“SELECT * FROM Employee”)

           fun findAllEmployeeNames(): LiveData<Employee>

@Database( entities = {Employee::class}, version = 1)

abstract class Databse : RoomDatabase() {

abstract fun employeeDAO(): EmployeeDAO

}