MVP
Skillson (Mindorks)What is MVP?
MVP
It is an architecture that provides code reusability and testability. By following this architecture it will be easy to update code in future. To work within a team we need to follow any architecture for code readability.
Why MVP
If we can write code easily in activities then why we need to follow any architecture, at a point of time it is good that your application is working fine but how to make changes in your code in future if needed, how you test if required. Implementing changes after a period of time seems to be a mess in your own written code in any application, how other or new team members implement changes.
To work within a team, we need ease in code readability for every team members, updating codes with ease in future also needs to be handled efficiently, it can only be done by following some architecture.
To overcome with all these issues we should follow MVP, as MVP has all the solution.
MVP application is divided into three parts.
- Model
- View
- Presenter
Let's understand these components in next page.
---------------------------------------------------------------
Model, View, Presenter
android-mvp-concept-diagram
Model
It handles the data part of the application. It does not interact directly with the view. It provides data to Presenter, and presenter forwards data to the view and intake data from presenter which is provided by the view. Model is not even aware of view and vice versa.
Model is divided into various parts, at center we have datamanager which is the single part of the model with which the presenter interacts, then datamanager on further interacts with other components of the model.
View
It handles the presentation of the layout. Its responsibility is to draw ui with data as per the instructions provided by Presenter. Activities, fragment, dialogs, custom views are the view part of the application.
Each view has a presenter.
Base of the view has atleast two parts as MvpView and Activity, among them MvpView is an interface and Activity is a class which implements MvpView. Base part of the view can further be divided into various parts as per the use cases.
Presenter
It is a gateway between model and view as they do not interact each other directly. Every data passes through this gateway. It updates the view by taking the data from the model and update the model with data provided by the view.
Base of the presenter also have a minimum of two parts, among them first is MvpPresenter as interface and second is BasePresenter as class implementing this interface. It’s base part can also be divided into various parts as per the use case.
------------------------------------------------------
MVP Implementation
As we are starting to explore MVP, let’s learn with very basic MVP sample Android project.
What is in this sample app, how it works?
At very first, we are having SplashActivity as launcher activity, it’s only work is to decide which activity to open, if already logged in, open MainActivity otherwise open LoginActivity.
Then on LoginActivity we have two edittext one to input email and another to input password and a login button, by clicking on this we move to MainActivity by storing the email to SharedPreferences, on the MainActivity we are showing email in textview by extracting it from SharedPreferences and we are having logout button too on MainActivity, by clicking on this we again moved back to LoginActivity by clearing all the SharedPreferences data.
Now it’s time to implement MVP.
Step 1.
Create a new android studio project.
At very first, create the model part as MVP initials is model.
Model
SharedPrefsHelper
It is called only by datamanager. Presenter never directly interacts with SharedPrefsHelper.
public class SharedPrefsHelper { public static final String MY_PREFS = "MY_PREFS"; public static final String EMAIL = "EMAIL"; SharedPreferences mSharedPreferences; public SharedPrefsHelper(Context context) { mSharedPreferences = context.getSharedPreferences(MY_PREFS, MODE_PRIVATE); } public void clear() { mSharedPreferences.edit().clear().apply(); } public void putEmail(String email) { mSharedPreferences.edit().putString(EMAIL, email).apply(); } public String getEmail() { return mSharedPreferences.getString(EMAIL, null); } public boolean getLoggedInMode() { return mSharedPreferences.getBoolean("IS_LOGGED_IN", false); } public void setLoggedInMode(boolean loggedIn) { mSharedPreferences.edit().putBoolean("IS_LOGGED_IN", loggedIn).apply(); } }
DataManager
It is the only part of model that interacts with presenter and vice versa, for interaction among other parts of model and presenter, datamanager acts as a middleman.
public class DataManager { SharedPrefsHelper mSharedPrefsHelper; public DataManager(SharedPrefsHelper sharedPrefsHelper) { mSharedPrefsHelper = sharedPrefsHelper; } public void clear() { mSharedPrefsHelper.clear(); } public void saveEmailId(String email) { mSharedPrefsHelper.putEmail(email); } public String getEmailId() { return mSharedPrefsHelper.getEmail(); } public void setLoggedIn() { mSharedPrefsHelper.setLoggedInMode(true); } public Boolean getLoggedInMode() { return mSharedPrefsHelper.getLoggedInMode(); } }
Step 2.
Now its time to create base for view Part.
View
MvpView
It is an interface that is implemented by BaseActivity, it acts as a base view that is extended by all other view interfaces.
public interface MvpView { }
BaseActivity
It is a base class for all activities, which implements MvpView and it is extended by all other activities in the application.
public class BaseActivity extends AppCompatActivity implements MvpView { }
Step 3.
Create base for Presenter part.
Presenter
MvpPresenter
It is an interface that is implemented by BasePresenter, it acts as base presenter interface that is extended by all other presenter interfaces.
public interface MvpPresenter<V extends MvpView> { void onAttach(V mvpView); }
BasePresenter
It is base class for all presenter that implements MvpPresenter and it is extended by all other presenters there in application.
public class BasePresenter<V extends MvpView> implements MvpPresenter<V> { private V mMvpView; DataManager mDataManager; public BasePresenter(DataManager dataManager){ mDataManager = dataManager; } @Override public void onAttach(V mvpView) { mMvpView = mvpView; } public V getMvpView() { return mMvpView; } public DataManager getDataManager() { return mDataManager; } }
As of now, we are done with creating base for MVP architecture. As we know MVP architecture is plug and play architecture, if we need anything more in base we can add or change that at any time, this is also the advantage of following MVP architecture.
-----------------------------------------------------------
Step 4.
In the previous page we were done with creating base for MVP architecture, it is time to create launcher activity of the app which is our SplashActivity.
First create interface for the view which extends MvpView.
SplashMvpView
public interface SplashMvpView extends MvpView { void openMainActivity(); void openLoginActivity(); }
SplashActivity
After creating the interface, create the class for the view which extends BaseActivity and implements the interface we have for this view.
public class SplashActivity extends BaseActivity implements SplashMvpView { SplashPresenter mSplashPresenter; public static Intent getStartIntent(Context context) { Intent intent = new Intent(context, SplashActivity.class); return intent; } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); DataManager dataManager = ((MvpApp) getApplication()).getDataManager(); mSplashPresenter = new SplashPresenter(dataManager); mSplashPresenter.onAttach(this); mSplashPresenter.decideNextActivity(); } @Override public void openMainActivity() { Intent intent = MainActivity.getStartIntent(this); startActivity(intent); finish(); } @Override public void openLoginActivity() { Intent intent = LoginActivity.getStartIntent(this); startActivity(intent); finish(); } }
As it is our launcher activity, make sure to change this as launcher activity in your AndroidManifest.
<activity android:name=".ui.splash.SplashActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
SplashMvpPresenter
First create interface for the Presenter which extends MvpPresenter.
public interface SplashMvpPresenter<V extends SplashMvpView> extends MvpPresenter<V> { void decideNextActivity(); }
SplashPresenter
After creating the interface, create class for the presenter which extends BasePresenter and implements the interface we have for this presenter.
public class SplashPresenter<V extends SplashMvpView> extends BasePresenter<V> implements SplashMvpPresenter<V> { public SplashPresenter(DataManager dataManager) { super(dataManager); } @Override public void decideNextActivity() { if (getDataManager().getLoggedInMode()) { getMvpView().openMainActivity(); } else { getMvpView().openLoginActivity(); } } }
Step 5.
What after SplashActivity ?
As per the app description, we need LoginActivity after SplashActivity.
CommonUtils
In the login activity we will be needing to verify email provided by users, following the architecture we can create this method in CommonUtils too.
public class CommonUtils { public static boolean isEmailValid(String email) { Pattern pattern; Matcher matcher; final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; pattern = Pattern.compile(EMAIL_PATTERN); matcher = pattern.matcher(email); return matcher.matches(); } }
LoginMvpView
public interface LoginMvpView extends MvpView { void openMainActivity(); void onLoginButtonClick(); }
LoginActivity
public class LoginActivity extends BaseActivity implements LoginMvpView { LoginPresenter loginPresenter; EditText editTextEmail, editTextPassword; Button button; public static Intent getStartIntent(Context context) { Intent intent = new Intent(context, LoginActivity.class); return intent; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); DataManager dataManager = ((MvpApp) getApplication()).getDataManager(); loginPresenter = new LoginPresenter(dataManager); loginPresenter.onAttach(this); editTextEmail = (EditText) findViewById(R.id.editTextEmail); editTextPassword = (EditText) findViewById(R.id.editTextPassword); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onLoginButtonClick(); } }); } @Override public void openMainActivity() { Intent intent = MainActivity.getStartIntent(this); startActivity(intent); finish(); } @Override public void onLoginButtonClick() { String emailId = editTextEmail.getText().toString(); String password = editTextPassword.getText().toString(); if (!CommonUtils.isEmailValid(emailId)) { Toast.makeText(this, "Enter correct Email", Toast.LENGTH_LONG).show(); return; } if (password == null || password.isEmpty()) { Toast.makeText(this, "Enter Password", Toast.LENGTH_LONG).show(); return; } loginPresenter.startLogin(emailId); } }
LoginMvpPresenter
public interface LoginMvpPresenter<V extends LoginMvpView> extends MvpPresenter<V> { void startLogin(String emailId); }
LoginPresenter
public class LoginPresenter<V extends LoginMvpView> extends BasePresenter<V> implements LoginMvpPresenter<V> { public LoginPresenter(DataManager dataManager) { super(dataManager); } @Override public void startLogin(String emailId) { getDataManager().saveEmailId(emailId); getDataManager().setLoggedIn(); getMvpView().openMainActivity(); } }
Step 6.
What after Logged in?Time to move on to MainActivity, now let’s create MainActivity.
MainMvpView
public interface MainMvpView extends MvpView { void openSplashActivity(); }
MainActivity
public class MainActivity extends BaseActivity implements MainMvpView { TextView textViewShow; Button buttonLogout; MainPresenter mainPresenter; public static Intent getStartIntent(Context context) { Intent intent = new Intent(context, MainActivity.class); return intent; } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DataManager dataManager = ((MvpApp) getApplication()).getDataManager(); mainPresenter = new MainPresenter(dataManager); mainPresenter.onAttach(this); textViewShow = (TextView) findViewById(R.id.textViewShow); buttonLogout = (Button) findViewById(R.id.buttonLogout); textViewShow.setText(mainPresenter.getEmailId()); buttonLogout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mainPresenter.setUserLoggedOut(); } }); } @Override public void openSplashActivity() { Intent intent = SplashActivity.getStartIntent(this); startActivity(intent); finish(); } }
MainMvpPresenter
public interface MainMvpPresenter<V extends MainMvpView> extends MvpPresenter<V> { String getEmailId(); void setUserLoggedOut(); }
MainPresenter
public class MainPresenter<V extends MainMvpView> extends BasePresenter<V> implements MainMvpPresenter<V> { public MainPresenter(DataManager dataManager) { super(dataManager); } @Override public String getEmailId() { return getDataManager().getEmailId(); } @Override public void setUserLoggedOut() { getDataManager().clear(); getMvpView().openSplashActivity(); } }
Step 7
MvpApp
public class MvpApp extends Application { DataManager dataManager; @Override public void onCreate() { super.onCreate(); SharedPrefsHelper sharedPrefsHelper = new SharedPrefsHelper(getApplicationContext()); dataManager = new DataManager(sharedPrefsHelper); } public DataManager getDataManager() { return dataManager; } }
Step 8
Android Manifest
Now add the name of the class that is extending application class in the app to application part of AndroidManifest.
<application android:name=".MvpApp" ...... ...... ...... ...... </application>
Step 9
Run your code, you are done with creating basic MVP sample app.
Check the complete project here
What next?
Refer the below links to learn how to build a complete MVP Android project.
- Essential Guide For Designing Your Android App Architecture: MVP: Part 1
- Android MVP Architecture Extension with Interactors and Repositories
If you want to explore MVVM, refer this link
https://github.com/MindorksOpenSource/android-mvvm-architecture