Android Architecture Components

 Android Architecture Components

To introduce the terminology, here is a short introduction to the Architecture Components and how they work together. Each component is explained more in the following sections. This diagram shows a basic form of this architecture. Recommended app architecture for apps using Architecture Components

Entity: The entity is an annotated class that describes a database table.

SQLite database: On the device, data is stored in an SQLite database. The Room persistence library creates and maintains this database for us

DAO: Data access object is a mapping of SQL queries to functions. We used to define these queries in a helper class, such as SQLiteOpenHelper. When we use a DAO, wer call the methods, and the components take care of the rest.

Room database: Database/Abstraction layer on top of SQLite database that takes care of the tasks that we used to handle with a helper class, such as SQLiteOpenHelper. It provides easier local data storage. The Room database uses the DAO to issue queries to the SQLite database.

Repository: A class that we create for managing multiple data sources.

ViewModel: Provides data to the UI and acts as a communication center between the Repository and the UI. Hides the backend from the UI. ViewModel instances survive device configuration changes.

LiveData: A data holder class, that follows the observer pattern, which means, that can be observed. Always holds/caches latest version of data & Notifies its observers when the data has changed. LiveData is lifecycle aware. UI components observe relevant data. LiveData automatically manages stopping and resuming observation, because it's aware of the relevant lifecycle status changes.

Entity annotations

For Room to work with an entity, we need to give Room information that relates the contents of the entity's Java class to what we want to represent in the database table. We do this using annotations.

Here are some commonly used annotations:

  • @Entity(tableName ="word_table") Each @Entity instance represents an entity in a table. Specify the name of the table if we want it to be different from the name of the class.
  • @PrimaryKey Every entity needs a primary key. To auto-generate a unique key for each entity, add and annotate a primary integer key with autoGenerate=true
  • @NonNull Denotes that a parameter, field, or method return value can never be null. The primary key should always use the @NonNull annotation. 
  • @ColumnInfo(name ="word") Specify the name of the column in the table, if wewant the column name to be different from the name of the member variable.

Every field that's stored in the database must either be public or have a "getter" method so that Room can access it. 

Here is annotated code representing a Person entity:

@Entity
public class Person {
    @PrimaryKey (autoGenerate=true)
    private int uid;

    @ColumnInfo(name = "first_name")
    private String firstName;

    @ColumnInfo(name = "last_name")
    private String lastName;

    // Getters and setters are not shown for brevity,
    // but they're required for Room to work if variables are private.
}

DAO (data access object)

To access our app's data using the Room persistence library, we need to work with data access objects, or DAOs. A set of Dao objects (DAOs) forms the main component of a Room database. Each DAO includes methods that offer abstract access to our app's database. RoomWordsSample app architecture diagram highlighting the DAO

We annotate the DAO to specify SQL queries and associate them with method calls. The compiler checks the SQL for errors, then generates queries from the annotations. For common queries, the libraries provide annotations, such as @Insert@Delete, and @Update.

Note that:

  • The DAO must be an interface or abstract class.
  • Room uses the DAO to create a clean API for your code.
  • By default, queries (@Query) must be executed on a thread other than the main thread. For operations such as inserting or deleting, Room takes care of thread management for us if we use the appropriate annotations.
  • The default action when you ask Room to insert an entity that is already in the database is to ABORT. We can specify a different conflict strategy, such as REPLACE.

Here is code that demonstrates these annotations along with different types of queries:

@Dao
public interface WordDao {

   // The conflict strategy defines what happens, 
   // if there is an existing entry.
   // The default action is ABORT. 
   @Insert(onConflict = OnConflictStrategy.REPLACE)
   void insert(Word word);

   // Update multiple entries with one call.
   @Update
   public void updateWords(Word... words);

   // Simple query that does not take parameters and returns nothing.
   @Query("DELETE FROM word_table")
   void deleteAll();

   // Simple query without parameters that returns values.
   @Query("SELECT * from word_table ORDER BY word ASC")
   List<Word> getAllWords();

   // Query with parameter that returns a specific word or words.
   @Query("SELECT * FROM word_table WHERE word LIKE :word ")
   public List<Word> findWord(String word);
}

LiveData

When

Comments

Popular posts from this blog

Android - Using KeyStore to encrypt and decrypt the data

Stack and Queue

Java Reflection API