Architecture Components
Architecture is a steady plan which needs to be made before the development process starts. Architecture components keep application organized, ties all component together and provide a collection of libraries that help you to design robust, verifiable and maintainable applications. Android’s new architecture suggests some key principles to create an ideal application with security and avoid bloated classes that are difficult to maintain and test.
Building Blocks
Basic examples for building blocks are Activity, View, Intents, Services, Fragments, Manifest File, AVD (Android Virtual Device). These blocks are the representation of rational application’s component architecture and also are marks of developer pain points.
The first set helps you with
- Automatically manage your activity and fragment lifecycles to avoid memory and resource leaks
- Persist Java data objects to an SQLite database
Components:
1. Lifecycle Components
This component is used to add lifecycle awareness. Lifecycle components includes Lifecycle, LifecycleOwner and LifecycleObserver
Lifecycle
So far lifecycle is an abstract class managed by the system itself. But in the current scenario, Lifecycle identify component’s state and behave & end task accordingly at the appropriate time.
LifecycleOwner
LifecycleOwner is an interface that can implement to get a lifecycle object from the getLifecycle() method. ProcessLifecycleOwner is useful when you want to manage the lifecycle of a whole process.
LifecycleObserver
LifecycleObserver observes LifecycleOwner components like Activities and Fragments. It receives LifecycleOwner.Event and react to them through the annotation methods.
By implementing this all together, we can create Lifecycle aware application.
-
Implementing Lifecycle observer
public class TestObserver implements LifecycleObserver { public MyObserver(Lifecycle lifecycle) { // Starts lifecycle observation lifecycle.addObserver(this); ... } // Annotated methods called when the associated lifecycle goes through these events @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void onResume() { } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void onPause() { } }
Now we can use this observer in our app component, using following implementation TestObserver observer = new TestObserver(aLifecycleOwner.getLifecycle());
2. LiveData
LiveData component is a data holder that contains a value that can be observed. With livedata whenever Activity or Fragment updated we will get notified so your UI will be always updated. It is a wrapper around your typical models that notify observers when something changes in that model. The Main advantage of livedata is no more memory leaks and NullPointerExceptions due to unexisting views.
-
Create LiveData objects
public class MyViewModel extends ViewModel { // Create a LiveData with a String private MutableLiveData<String> mData; public MutableLiveData<String> getData() { if ( mData == null) { mData = new MutableLiveData<String>(); } return mData; } }
-
Observe LiveData objects
The following code illustrates how to observe LiveData object: public class MyActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyViewModel model = ViewModelProviders.of(this).get(MyViewModel .class); model.getData().observe(this, data -> { // update UI }); } }
3. View Model
ViewModel useful to provide and maintain data for your UI components (Activity or Fragment) in a lifecycle conscious way. It is able to survive through the configuration changes. So if you destroy activity or change your phone orientation you won’t lose ViewModel and data. Due to LiveData instance that is placed under ViewModel class, the input from our end isn’t required.
You don’t need to worry about UI lifecycle of holder data in UI. ViewModel will be build automatically through a factory and you don’t require to handle creating it and demolishing on your own.
-
Implement a ViewModel
It’s illustrated by the following sample code: public class MyViewModel extends ViewModel { private MutableLiveData<List<Students>> students; public LiveData<List<Students>> getStudents () { if ( students == null) { students = new MutableLiveData<List<Students>>(); loadStudents(); } return students; } private void loadStudents () { // Do an asynchronous operation to fetch students. } }
You can access this list from an activity as follows:
public class MyActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { // Create a ViewModel the first time the system calls an activity's onCreate() method. // Re-created activities receive the same MyViewModel instance created by the first activity. MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); model.getStudents ().observe(this, students -> { // update UI }); } }
4. Room
Room is a database library & a great alternative for SQLite database. To use SQLite database it is always necessary to write a lot of boilerplate. We can define database by adding annotations in Model class. The library helps to create a cache of app’s data on a device. It is much similar to OrmLite.
There are 3 major components in Room:
a. Database
As your app is persisted, relational data and contains the database holder, It Serves as the chief access point for the underlying connection to the class that’s annotated with @Database should satisfy the following conditions:
Be an abstract class that extends RoomDatabase.
Include the list of entities connected with the database incorporating the annotation.
It returns the class that is annotated with @Dao and contains an abstract method that has 0 arguments.
While at the runtime, you can get an instance of database through calling Room.inMemoryDatabaseBuilder() or else Room.databaseBuilder().
b. Entity
Represents a table within the database.
c. DAO
Contains the methods used for accessing the database.
-
Creating entity
@Entity public class User { @PrimaryKey private int uid; @ColumnInfo(name = "first_name") private String firstName; @ColumnInfo(name = "last_name") private String lastName; // Getters and setters are ignored for brevity, // but they're required for Room to work. }
-
Create database
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase INSTANCE; public static AppDatabase getDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "my_db").build(); } return INSTANCE; } }
This class is used to create the database and get an instance of it. We create the database using following code.
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, “my_db”).build();
-
Create the Data Access Object
Annotate the class with the @Dao annotation. A class implementation will then be generated by Room that implements the methods defined in the interface (very similar to how Retrofit works).
@Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Delete void delete(User user); }
Conclusion
This article gives you a basic knowledge of android architecture components. We have tried to include all topics related to newly proposed android architecture which solve all relevant issues which are faced by the developer while application development. Still, if you find any issues, consider Hire Android Developer of Elsner Technology.
About Author
Pankaj Sakariya - Delivery Manager
Pankaj is a results-driven professional with a track record of successfully managing high-impact projects. His ability to balance client expectations with operational excellence makes him an invaluable asset. Pankaj is committed to ensuring smooth delivery and exceeding client expectations, with a strong focus on quality and team collaboration.