- This guide encompasses best practices and recommended architecture for building robust, production-quality apps.
- The most important principle in MVVM architecture is to follow the separation of concerns. It’s a common mistake to write all your code in an Activity or a Fragment and it produce memory leaks and hard to maintain our code and hard to debug our code.
- Due to above reason we use MVVM architecture pattern, in MVVM architecture we separate our codebase in multiple classes and file which help us to avoid memory leaks and easy to debug our code and write maintainable code easily.
MVVM Architecture Diagram
- As show in image we separate our code in multiple classes and file
-
- Activity / Fragment :- This classes is only responsible for showing data on user interface and get data from user interface and data comes from the ViewModel, Activity doesn’t have knowledge about how data comes and from where it comes from the purpose of this classes is to only show data on User interface.
- ViewModel :- This class is used to provide data to the user interface and it survive the configuration changes like device orientation changes, ViewModel get data from the repository.
- Repository :- This class is generalized or common class for data, In android application, data comes from the different ways like from the SQLite database and from the remote server so this repository class is common gateway for the data which get data from the SQLite database and from API services like retrofit.
- Model :- This class is only responsible for getting data from the SQLite database and pass data to the repository.
- Remote Data Source :- This classes is only responsible for getting data from the Remote server or it contain code for calling APIs and pass data to the repository.
-
Brief Explanation of MVVM Code Structure And Data Flow
- As explain above inside activity or fragment data comes from the viewmodel only and all business logic of code for provide data to the user interface is comes from the viewmodel class and viewmodel also drive data from the repository which is common class to get data from the separate sources like SQLite database and Remote server, At last model class is get data from the local SQLite database and pass it to the repository, same as model class remote data source class is also fetch data from the server and pass it to the repository, so this is the basic structure of MVVM architecture in android.
Demo Code Structure
- As Explain in architecture we separate our code in multiple classes
- MainActivity :- This class is show data on user interface
- MainActivityViewModel :- This class is get data from the Repository
- Repositoy :- This class is get data from the RemoteDataSource and LocalDatabaseModel.
- RemoteDataSource :- This class is get data from the remote server and contain all coderelate to API calls in our project.
- LocalDatabaseModel :- This class is responsible to get data from the local database and contain all query code of database in out project.
- XML Code :-
<?xml version="1.0" encoding="utf-8"?> <androidx.appcompat.widget.LinearLayoutCompat 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" android:layout_gravity="center" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity"> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/download"/> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:textSize="21sp" android:layout_marginTop="20dp" android:layout_gravity="center_horizontal"/> <TextView android:id="@+id/remote" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:textSize="21sp" android:layout_marginTop="20dp" android:layout_gravity="center_horizontal"/> <Button android:id="@+id/local_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:backgroundTint="#40A9D3" android:text="Get Local Data"/> <Button android:id="@+id/remote_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:backgroundTint="#40A9D3" android:text="Get Remote Data"/> </androidx.appcompat.widget.LinearLayoutCompat>
1. MainActivity :-
public class MainActivity extends AppCompatActivity { private MainActivityViewModel mainActivityViewModel; private TextView localDataBaseTextView, serverDataTextView; private Button getLocalDatabaseData, getServerData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class); initializeViews(); } private void initializeViews() { localDataBaseTextView = findViewById(R.id.name); serverDataTextView = findViewById(R.id.remote); getLocalDatabaseData = findViewById(R.id.local_data); getLocalDatabaseData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String data = mainActivityViewModel.getDataFromLocalDatabase(); localDataBaseTextView.setText(data); } }); getServerData = findViewById(R.id.remote_data); getServerData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String data = mainActivityViewModel.getDataFromTheServer(); serverDataTextView.setText(data); } }); } }
2. MainActivityViewModel :-
public class MainActivityViewModel extends ViewModel { /* * ViewModel get data from the repository * * */ Repository repository; // create object of repository class public MainActivityViewModel(){ repository = new Repository(); } // this method get data from the local database which comes from the repository public String getDataFromLocalDatabase(){ String mySQLiteData = repository.getLocalData(); return mySQLiteData; } // this method get data from the server which comes from the server, Api calling public String getDataFromTheServer(){ String myServerData = repository.getServerData(); return myServerData; } }
3. Repositoy :-
public class Repository { /* * In this class all data relate code comes inside it view different resources * * */ private LocalDatabaseModel localDataBaseDataSources; private RemoteDataSource remoteDataSources; public Repository(){ localDataBaseDataSources = new LocalDatabaseModel(); remoteDataSources = new RemoteDataSource(); } // this method is responsible for getting data from the database via MainActivityModel class public String getLocalData(){ return localDataBaseDataSources.getMyDataFromTheDatabase(); } // this method is responsible for getting data from the server view MainAcivityRemoteDataSources class public String getServerData(){ return remoteDataSources.getMyDataFromTheServer(); } }
4. RemoteDataSource :-
public class RemoteDataSource { /* * this class is contain logic to get data from the server via api calls * at this step we only pass static string for testing purpose * * */ public String getMyDataFromTheServer(){ return "Data Comes From The Server"; } }
5. LocalDatabaseModel :-
public class LocalDatabaseModel { /* * this class is responsible to get data from the local database only * At this step we only return static string but is can be a complex query and contain multiple query methods as well * * */ public String getMyDataFromTheDatabase(){ return "Data comes from Sqlite Database"; } }