In this article, I will explain how to implement MVVM pattern with Android Architecture Components. Android Architecture components contain a bunch of libraries that will help you to build android applications in the MVVM pattern. Few of them are Room, ViewModel, LiveData. Before going to example let’s understand these components one by one.
Lifecycle-Aware Components
These are the components that automatically responds according to life-cycle events. These components will help you produce better, lightweight, easier to maintain code. Take the example of LocationListener. When we create LocationListener in Activity we have to manage its connectivity. When activity launches we have started listening to location changes. Now when activity pauses we have to pause listening to location changes. But now with Lifecycle-Awareness of the component, we don’t need to handle pausing location updates. Just pass the lifecycle owner to the component and rest will be taken care of by the component itself.
ViewModel
The ViewModel is used to persist data during various configuration changes like screen rotation. Suppose we are fetching data from the server inside the activity. Now if we did not persist data inside ViewModel. The user rotates the screen then it will again fetch data which is a costly process. To avoid these unnecessary transactions to the server we can use ViewModel.
LiveData
LiveData is a data holder class. Data inside this holder can be observed for changes. So we can add data and keep track of data changes to modify UI accordingly. LiveData is lifecycle-aware that is it responds according to the state of activity or fragment. It keeps your UI up to date with the latest data. It avoids memory leaks as data get cleared as the associated lifecycle is destroyed. no crashes due to stopped activities. You can create a single point of contact for data retrieval that keeps your code robust, clean, and easier to maintain.
Room Persistence Library
Room Persistence Library provides an abstraction layer over the SQLite database. The room makes database CRUD operations easier and more maintainable. The room shows an error if you have written the wrong query while compiling your application. Room works with LiveData to keep your UI and Data in sync. Room uses entities for structuring database and dao( data access object ) to perform CRUD( Create, Read, Update, Delete) operations. we will see more about it as we go in this article.
Repository
The repository can be called a single source of truth for all application data. When we have both local and online database then it becomes hard to manage both databases. With Repository we can create a single source for any type of data source. Now data coming from a single source will make code easier to maintain.
Demo
Download Project
MVVM in Android with Room, LiveData and ViewModel
Below is stranded MVVM architecture in android using Room, LiveData, and ViewModel. Using this architecture we will build notes application. In this application, we will be able to add notes and display notes in recycler view.
Android Architecture Components | MVVM in Android with Room, LiveData, and ViewModel
Adding Room, LiveData, ViewModel Library to Android Studio Project
Create new or open an existing android studio project. Open build.greadle(module app). Add dependencies for Room, LiveData, ViewModel as shown below. CardView dependency is optional due to the design requirement of this example.
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.loopwiki.androidarchitecturecomponants"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '27.0.3'
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
implementation 'com.android.support:design:27.1.1'
// ViewModel and LiveData library depenedecies
implementation 'android.arch.lifecycle:extensions:1.1.1'
implementation 'com.android.support:support-v4:27.1.1'
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
// Room library depenedecies
implementation 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
//CardView dependency optional required in design of example
implementation 'com.android.support:cardview-v7:27.1.1'
}
Project Structure
Create packages for activities, adapters, databases, repositories, utils, viewModels, Daos, and models. This will maintain the project in a good structure.

Creating Entity
Create new class in Package Name --> database.-> models -> Note.java. This class will represent the note structure in the database. The note will have a unique id, title, description, and created as shown below.
package com.loopwiki.androidarchitecturecomponants.database.models;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;
import android.arch.persistence.room.TypeConverters;
import com.loopwiki.androidarchitecturecomponants.utils.DateConverter;
import java.util.Date;
// Entity class model of room database
@Entity
public class Note {
// room database entity primary key
@PrimaryKey(autoGenerate = true)
public int id;
private String noteTitle;
private String noteDescription;
//type converter for date
@TypeConverters(DateConverter.class)
private Date createdAt;
public Note(String noteTitle, String noteDescription, Date createdAt) {
this.noteTitle = noteTitle;
this.noteDescription = noteDescription;
this.createdAt = createdAt;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNoteTitle() {
return noteTitle;
}
public void setNoteTitle(String noteTitle) {
this.noteTitle = noteTitle;
}
public String getNoteDescription() {
return noteDescription;
}
public void setNoteDescription(String noteDescription) {
this.noteDescription = noteDescription;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
}
Now we can not store data directly we need type converter for that so create new class Package Name -> utils -> DateConverter.java. Add the following lines of code into it.
package com.loopwiki.androidarchitecturecomponants.utils;
import android.arch.persistence.room.TypeConverter;
import android.text.format.DateFormat;
import java.util.Date;
public class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
@TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
public static String getDayMonth(Date date) {
String day = (String) DateFormat.format("dd", date); // 20
String monthString = (String) DateFormat.format("MMM", date); // Jun
return day + monthString;
}
}
Creating Dao( Data Access Object)
Dao( Data Access Object) used to perform CRUD operations on the database. Create new class Package Name -> database -> NoteDao.java. Define Methods to insert, delete, getting all notes as shown below.
package com.loopwiki.androidarchitecturecomponants.database.Daos;
import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.TypeConverters;
import com.loopwiki.androidarchitecturecomponants.utils.DateConverter;
import com.loopwiki.androidarchitecturecomponants.database.models.Note;
import java.util.List;
import static android.arch.persistence.room.OnConflictStrategy.REPLACE;
//note dao(data access object)
@Dao
@TypeConverters(DateConverter.class)
public interface NoteDao {
// Dao method to get all notes
@Query("SELECT * FROM Note")
LiveData<List<Note>> getAllNotes();
// Dao method to insert note
@Insert(onConflict = REPLACE)
void insertNote(Note note);
// Dao method to delete note
@Delete
void deleteNote(Note note);
}
Creating Room Database
Create new abstract class extending RoomDatabase inside Package Name -> database -> NoteDatabase.java. This class used to create an instance of Room Database. Inside this class provide all entities and dao’s. The structure of this class is as shown below.
package com.loopwiki.androidarchitecturecomponants.database;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;
import com.loopwiki.androidarchitecturecomponants.database.Daos.NoteDao;
import com.loopwiki.androidarchitecturecomponants.database.models.Note;
// Room database class
@Database(entities = Note.class, version = 1, exportSchema = false)
public abstract class NoteDatabase extends RoomDatabase {
//define static instance
private static NoteDatabase mInstance;
//method to get room database
public static NoteDatabase getDatabase(Context context) {
if (mInstance == null)
mInstance = Room.databaseBuilder(context.getApplicationContext(),
NoteDatabase.class, "notes_db")
.build();
return mInstance;
}
//method to remove instance
public static void closeDatabase() {
mInstance = null;
}
//define note dao ( data access object )
public abstract NoteDao noteDao();
}
Creating Repository
Create new class Package Name -> repositories -> NotesRepository.java. This class will serve as a true source of data. Create methods to get data from Room database or any other database like firebase. Inside create LiveData of List of all notes and methods to add a note inside Room Database as shown below.
package com.loopwiki.androidarchitecturecomponants.repositories;
import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import com.loopwiki.androidarchitecturecomponants.database.Daos.NoteDao;
import com.loopwiki.androidarchitecturecomponants.database.NoteDatabase;
import com.loopwiki.androidarchitecturecomponants.database.models.Note;
import java.util.List;
//Notes repository
public class NotesRepository {
//Live Data of List of all notes
private LiveData<List<Note>> mAllNotes;
//Define Notes Dao
NoteDao mNoteDao;
public NotesRepository(@NonNull Application application) {
NoteDatabase noteDatabase = NoteDatabase.getDatabase(application);
//init Notes Dao
mNoteDao = noteDatabase.noteDao();
//get all notes
mAllNotes = mNoteDao.getAllNotes();
}
//method to get all notes
public LiveData<List<Note>> getAllNotes() {
return mAllNotes;
}
//method to add note
public void addNote(Note note) {
new AddNote().execute(note);
}
//Async task to add note
public class AddNote extends AsyncTask<Note, Void, Void> {
@Override
protected Void doInBackground(Note... notes) {
mNoteDao.insertNote(notes[0]);
return null;
}
}
}
We will display all notes inside recycler view. Before creating activity we will create an adapter and required layouts for recyclerview.
Creating Adapter for Recyclerview
Create new file in res -> layout -> custom_row_note.xml. This row will represent the view of a single note in recyclerview as shown below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/backStrip"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:background="@android:color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="8dp"
android:layout_marginLeft="4dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/noteTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
<TextView
android:id="@+id/noteDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/createdAt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/colorPrimary" />
</LinearLayout>
</RelativeLayout>
</FrameLayout>
</android.support.v7.widget.CardView>
Create new class inside Package Name -> adapters -> NotesAdapter.java. This class will serve as an adapter for recyclerview. Create viewholder and bind data to the view inside onCreateViewHolder() and onBindViewHolder() methods respectively as shown below.
package com.loopwiki.androidarchitecturecomponants.adapters;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.loopwiki.androidarchitecturecomponants.utils.DateConverter;
import com.loopwiki.androidarchitecturecomponants.R;
import com.loopwiki.androidarchitecturecomponants.database.models.Note;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class NotesAdapter extends RecyclerView.Adapter {
//Create list of notes
List<Note> notes = new ArrayList<>();
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//Get layout inflater
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
//Inflate layout
View row = inflater.inflate(R.layout.custom_row_note, parent, false);
//return notes holder and pass row inside
return new NoteHolder(row);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
//Get current note
Note currentNote = notes.get(position);
//cast notes holder
NoteHolder noteHolder = (NoteHolder) holder;
//set title description and created at
noteHolder.mNoteTitle.setText(currentNote.getNoteTitle());
noteHolder.mNoteDescription.setText(currentNote.getNoteDescription());
noteHolder.createdAt.setText(DateConverter.getDayMonth(currentNote.getCreatedAt()));
//create random color and set it
Random rnd = new Random();
int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
noteHolder.backStrip.setBackgroundColor(color);
}
@Override
public int getItemCount() {
return notes.size();
}
public class NoteHolder extends RecyclerView.ViewHolder {
TextView mNoteTitle, mNoteDescription, createdAt;
FrameLayout backStrip;
public NoteHolder(View itemView) {
super(itemView);
mNoteTitle = itemView.findViewById(R.id.noteTitle);
mNoteDescription = itemView.findViewById(R.id.noteDescription);
createdAt = itemView.findViewById(R.id.createdAt);
backStrip = itemView.findViewById(R.id.backStrip);
}
}
public void addNotes(List<Note> notes) {
this.notes = notes;
notifyDataSetChanged();
}
}
Create new class inside Package Name -> utils -> Space.java. This class is recyclerview decoration class used to add space between recyclerview items. Add the following lines to it
package com.loopwiki.androidarchitecturecomponants.utils;
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.DimenRes;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class Space extends RecyclerView.ItemDecoration {
private int mItemOffset;
public Space(int itemOffset) {
mItemOffset = itemOffset;
}
public Space(@NonNull Context context, @DimenRes int itemOffsetId) {
this(context.getResources().getDimensionPixelSize(itemOffsetId));
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (parent.getChildLayoutPosition(view) == 0)
outRect.top = mItemOffset;
outRect.left = mItemOffset;
outRect.right = mItemOffset;
outRect.bottom = mItemOffset;
}
}
Creating ViewModel
It’s time to create viewmodel for notes. Create class inside Package name -> viewModels -> NotesListViewModel.java. This ViewModel will contain LiveData of all notes and methods to insert notes as defined below.
package com.loopwiki.androidarchitecturecomponants.viewModels;
import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import com.loopwiki.androidarchitecturecomponants.repositories.NotesRepository;
import com.loopwiki.androidarchitecturecomponants.database.models.Note;
import java.util.List;
public class NotesListViewModel extends AndroidViewModel {
private LiveData<List<Note>> mAllNotes;
NotesRepository mNotesRepository;
public NotesListViewModel(@NonNull Application application) {
super(application);
mNotesRepository = new NotesRepository(application);
mAllNotes = mNotesRepository.getAllNotes();
}
public LiveData<List<Note>> getAllNotes() {
return mAllNotes;
}
public void addNote(Note note) {
mNotesRepository.addNote(note);
}
}
Creating Activity
Finally create new layout res -> layout -> content_main.xml. Inside this layout define recyclerview as given below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".activities.MainActivity"
tools:showIn="@layout/activity_main">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerViewNotes"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
Create one more layout res -> layout -> activity_main.xml. This layout will contain contain_main.xml, app bar, floating action button inside coordinator layout as below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
app:layout_scrollFlags="snap|enterAlways|scroll"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:src="@drawable/ic_add_black_24dp"
android:tint="@android:color/white"
android:layout_margin="16dp" />
</android.support.design.widget.CoordinatorLayout>
Create custom layout for add note dialogue res -> layout -> add_note_dialog.xml. Add the following code to it.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="Add Note"
android:textAppearance="@style/TextAppearance.AppCompat.Large.Inverse" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:hint="Title">
<android.support.design.widget.TextInputEditText
android:id="@+id/editTextTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:hint="Description">
<android.support.design.widget.TextInputEditText
android:id="@+id/editTextDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end|right"
android:orientation="horizontal">
<TextView
android:id="@+id/textViewAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="Add"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/colorPrimary" />
<TextView
android:id="@+id/textViewCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="Cancel"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/colorPrimary" />
</LinearLayout>
</LinearLayout>
Create new class Package Name -> activities -> MainActivity.java. Bind recyclerview and other views inside activity. Then get ViewModel for the activity using ViewModelProviders as shown below. showDialog() method used to show add notes dialogue.
package com.loopwiki.androidarchitecturecomponants.activities;
import android.app.Dialog;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.EditText;
import android.widget.TextView;
import com.loopwiki.androidarchitecturecomponants.R;
import com.loopwiki.androidarchitecturecomponants.adapters.NotesAdapter;
import com.loopwiki.androidarchitecturecomponants.database.models.Note;
import com.loopwiki.androidarchitecturecomponants.utils.Space;
import com.loopwiki.androidarchitecturecomponants.viewModels.NotesListViewModel;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class MainActivity extends AppCompatActivity {
NotesListViewModel mNotesListViewModel;
FloatingActionButton fab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Initialize floating action button
fab = (FloatingActionButton) findViewById(R.id.fab);
//show add notes dialogue
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showDialog();
}
});
// bind recyclerview to object
RecyclerView mNotesRecyclerView = findViewById(R.id.recyclerViewNotes);
// set layout manager
mNotesRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// create new notes adapter
final NotesAdapter notesAdapter = new NotesAdapter();
// set adapter to recyclerview
mNotesRecyclerView.setAdapter(notesAdapter);
// add decoration to recyclerview
mNotesRecyclerView.addItemDecoration(new Space(20));
// get ViewModel of this activity using ViewModelProviders
mNotesListViewModel = ViewModelProviders.of(this).get(NotesListViewModel.class);
// observe for notes data changes
mNotesListViewModel.getAllNotes().observe(this, new Observer<List<Note>>() {
@Override
public void onChanged(@Nullable List<Note> notes) {
//add notes to adapter
notesAdapter.addNotes(notes);
}
});
}
public void showDialog() {
fab.hide();
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.add_note_dialog);
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final EditText editTextTitle = dialog.findViewById(R.id.editTextTitle);
final EditText editTextDescription = dialog.findViewById(R.id.editTextDescription);
TextView textViewAdd = dialog.findViewById(R.id.textViewAdd);
TextView textViewCancel = dialog.findViewById(R.id.textViewCancel);
textViewAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String Title = editTextTitle.getText().toString();
String Description = editTextDescription.getText().toString();
Date createdAt = Calendar.getInstance().getTime();
//add note
mNotesListViewModel.addNote(new Note(Title, Description, createdAt));
fab.show();
dialog.dismiss();
}
});
textViewCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
fab.show();
}
});
dialog.show();
}
}
Modify colors.xml, styles.xml, manifest.xml as below.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#ffc107</color>
<color name="colorPrimaryDark">#ffa000</color>
<color name="colorAccent">#6200ea</color>
</resources>
<resources>
<string name="app_name">Android Architecture Componants</string>
</resources>
<resources>
<! – Base application theme. – >
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<! – Customize your theme here. – >
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>
Run application
If you still have any queries, please post them in the comments section below, I will be happy to help you.
3 Comments
Thankssss, You are save my final project
welcome buddy
Hi nice elaborate tutorial. How can I represent the created date as days ago? 4 days ago