I'm currently developing an android app using MVP Pattern.
When I try to develop an Activity, I should use a ListView. So I'm using Adapter for ListView. But I heard Adapter is similar to Presenter on MVP Pattern.
I think if Apdater is smiliar to Presenter, then I should make Presenter for updating ListView instead of Adapter.
When this situation, how to develop ListView? Just use Adapter and keep using MVP Pattern?
Thanks for your reading.
MVP (Model — View — Presenter) architecture is one of the most popular architecture patterns and is valid in organizing the project. MVP (Model — View — Presenter) comes into the picture as an alternative to the traditional MVC (Model — View — Controller) architecture pattern.
MVVM is better than MVC/MVP because of its unidirectional data and dependency flow. Dependency is one way, thus it is a lot easier to decouple it when we need to. It is also easier for testing. All my projects(written in Kotlin for Android app) are based on MVVM.
In the MVP design pattern, the presenter manipulates the model and also updates the view. In MVP View and Presenter are completely decoupled from each other's and communicate to each other's by an interface.
Adapter is part of the view. In fact, all Android dependencies should be a part of the view. To keep the adapter isolated from your model and your presenter use to be a hard task. I have released a library called PaperKnife for this purpose.
You can use PaperKnife to decouple the adapter from the model and the presenter layer. Follow the next steps:
Abstract the model layer using CellElement
interface. Your view layer does't need to know your model.
Create a class to provide the information for your row view. You can use your presenter. Implements the class CellDataProvider
and create methods to provide all the information. Annotate your provider methods with @DataSource("DataId")
to perform the mapping. Your data methods receive the instance of your model class. For example:
public class SamplePresenterImpl implements SamplePresenter, CellDataProvider {
@DataSource("Title")
public String getTitle(Item item) {
return item.getTitle();
}
// etc.
}
Create a ViewHolder
in your adapter and implements the CellViewHolder
interface. Create methods to manage the views and use DataTarget("DataId")
static class ViewHolder extends CellViewHolder {
@DataTarget("Title")
public String setTitle(String title) {
mTextViewTitle.setText(title);
}
}
Execute the mapping in your adapter getView
method:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// etc.
PaperKnife.map(mList.get(position))
.dataProvider(mCellDataProvider)
.into(viewHolder);
return convertView;
}
In this way your view layer just know the CellElement
interface, and your presenter is responsible to provide data to your adapter.
Yes, the Adapter should be the P component in an MVP pattern. In fact ListViews are pretty much written as MVP- the getView() function needs to set all the values of the view each time its called, that's almost the definition of what a presenter must do. Although it's also easy to use it in an MVC type way- simply have getView call functions on the View that pass it the model and do that work in the Views. So really either way will work, just pick your preference.
If you do use an MVP model with complex list rows, I like to make the rows a custom compound View and put more descriptive function names on it- so rather than going listRow.findViewById(R.id.textView).setText(filename) I'll go listRow.setFilename(filename) and let the view know what to do with that. That kind of blurs the bounds of MVP and MVC a bit, but I find it a good balance of readability of your adapter and avoiding some of the awkwardness pure MVC sometimes brings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With