How to control ListView with MVP Pattern for Android

Originerd picture Originerd · Jul 21, 2014 · Viewed 9.4k times · Source

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.

Answer

albertovecina picture albertovecina · Sep 8, 2015

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:

  1. Abstract the model layer using CellElement interface. Your view layer does't need to know your model.

  2. 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.
    }
    
  3. 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);
        }
    }
    
  4. 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.