MVP
Amit Nadiger
Polyglot(Rust??, C++ 11,14,17,20, C, Kotlin, Java) Android TV, Cas, Blockchain, Polkadot, UTXO, Substrate, Wasm, Proxy-wasm,AndroidTV, Dvb, STB, Linux, Engineering management.
MVP, or Model-View-Presenter, is a software architectural pattern commonly used in Android development. It is a variation of the traditional MVC pattern and focuses on separating the presentation logic from the view and the data manipulation from the model. Here's a detailed explanation of MVP in the context of Android:
? ? +-------------------+
? ? |? ?View/Activity? ?|
? ? +---------+---------+
? ? ? ? ? ? ? |
? ? ? ? ? ? ? |? ?Creates
? ? ? ? ? ? ? |
? ? +---------v---------+
? ? |? ? ? Presenter? ? |
? ? +---------+---------+
? ? ? ? ? ? ? |
? ? ? ? ? ? ? |? ?Updates
? ? ? ? ? ? ? |
? ? +---------v---------+
? ? |? ? ? ?Model? ? ? ?|
? ? +-------------------+
In the MVP architecture:
The main goal of MVP is to decouple the view and the model by introducing a separate presenter layer. This separation allows for better testability, as the presenter can be easily unit tested without requiring an Android device or emulator. It also promotes modularity and reusability, as the view and the model can be modified or replaced independently without affecting other components.
In Android, MVP is commonly used to build complex user interfaces, especially when dealing with activities and fragments. The view interfaces define the contract between the view and the presenter, ensuring loose coupling. The presenter holds a reference to the view interface and manages its lifecycle callbacks, user interactions, and data updates. The model is responsible for providing the necessary data to the presenter, which then updates the view accordingly.
MVP in Android has some advantages, including better separation of concerns, improved testability, and easier maintenance. However, it also introduces additional complexity compared to simpler patterns like MVC. The presence of the presenter layer can make the codebase larger and more complex, requiring careful design and management.
Communication flow:
Limitations :
Example :
Let's assume we're building a simple login screen. Here's how the different components of MVP would be implemented:
-------------------------------------------------------------------------------------------
Model: The model represents the data and business logic. In this case, it would include classes for user authentication, such as a UserRepository or a UserDataSource.
IUserRepository Interface:
interface IUserRepository {
? ? fun authenticate(username: String, password: String): Boolean
}
UserRepository Implementation:
class UserRepository : IUserRepository {
? ? override fun authenticate(username: String, password: String): Boolean {
? ? ? ? // Perform authentication logic here
? ? ? ? // Return true if authentication is successful, false otherwise
? ? ? ? return (username == "admin" && password == "password")
? ? }
}
-------------------------------------------------------------------------------------------
View:The view is responsible for displaying the user interface and capturing user input. It should have minimal logic and delegate most actions to the presenter. In this example, we'll use an Activity as the view.
The view interface, ILoginActivityView, defines the contract between the view and the presenter. It includes methods like showLoading(), showSuccess(), showError(), etc., to update the UI based on the authentication result.
interface ILoginActivityView {
? ? fun showLoading()
? ? fun showSuccess()
? ? fun showError(message: String)
}
-------------------------------------------------------------------------------------------
领英推荐
Presenter:The presenter acts as an intermediary between the view and the model. It contains the logic for handling user interactions and business operations.
The presenter interface, ILoginActivityPresenter, defines the contract between the presenter and the view. It includes methods like login(username, password) to initiate the authentication process.
interface ILoginActivityPresenter {
? ? fun login(username: String, password: String)
}
The presenter implementation, LoginActivityPresenterImpl, implements the ILoginActivityPresenter interface. It interacts with the model (UserRepository) to perform authentication and updates the view based on the result.
class LoginActivityPresenterImpl(
? ? private val view: ILoginActivityView,
? ? private val userRepository: IUserRepository
) : ILoginActivityPresenter {
? ? override fun login(username: String, password: String) {
? ? ? ? // Show loading state on the view
? ? ? ? view.showLoading()
? ? ? ? // Perform authentication using the IUserRepository
? ? ? ? val result = userRepository.authenticate(username, password)
? ? ? ? // Update the view based on the authentication result
? ? ? ? if (result) {
? ? ? ? ? ? view.showSuccess()
? ? ? ? } else {
? ? ? ? ? ? view.showError("Invalid credentials")
? ? ? ? }
? ? }
}
-----------------------------------------------------------------------------------
Putting it all together:In the Activity class, we instantiate the presenter and handle user interactions.
class LoginActivity : AppCompatActivity(), ILoginActivityView {
? ? private lateinit var presenter: ILoginActivityPresenter
? ? override fun onCreate(savedInstanceState: Bundle?) {
? ? ? ? super.onCreate(savedInstanceState)
? ? ? ? setContentView(R.layout.activity_login)
? ? ? ? // Create the presenter with dependencies (view and model)
? ? ? ? presenter = LoginActivityPresenterImpl(this, UserRepository())
? ? ? ? // Handle login button click
? ? ? ? loginButton.setOnClickListener {
? ? ? ? ? ? val username = usernameEditText.text.toString()
? ? ? ? ? ? val password = passwordEditText.text.toString()
? ? ? ? ? ? // Delegate login action to the presenter
? ? ? ? ? ? presenter.login(username, password)
? ? ? ? }
? ? }
? ? override fun showLoading() {
? ? ? ? // Show loading state on the UI (e.g., display a progress bar)
? ? ? ? progressBar.visibility = View.VISIBLE
? ? }
? ? override fun showSuccess() {
? ? ? ? // Show success message on the UI (e.g., navigate to the home screen)
? ? ? ? Toast.makeText(this, "Login successful", Toast.LENGTH_SHORT).show()
? ? }
? ? override fun showError(message: String) {
? ? ? ? // Show error message on the UI (e.g., display an error message)
? ? ? ? Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
? ? }
}
In this updated example, the UserRepository class represents the model. It handles the authentication logic and returns a Boolean result. The LoginActivityView interface and LoginActivityPresenter interface define the contract between the view and the presenter, and the LoginActivityPresenterImpl implements the presenter interface, interacting.
The above code is still not perfect , since dependencies are tightly coupled .
We need to inject or provide the dependency from outside .
It looks MVP and MVC are similar( Looks like C in MC is replaced by P in MVP), however there is difference between them:
Both patterns have their advantages and are suitable for different scenarios. MVC is more traditional and widely used, while MVP provides better separation of concerns and testability. The choice between them depends on the specific requirements and preferences of the project.
While they have similarities, there are some key differences between them:
3. Dependency Direction:
4. Testability:
5. Code Organization:
Thanks for reading , please comment if you have any.