0

I have an Android MVP project. I want to keep out any Android references out of the presenter. This way, I can keep UI separated in the Activity/View.

There is a ListView in the Activity which uses a custom ArrayList in the adapter (MyAdapter). This uses MyModel objects to populate the ListView with data.

Now, I'm trying to initialize the adapter and the ListView.

By doing that on the activity I would end up with something like

`MyAdapter adapter = new MyAdapter<MyModel>(this, R.layout.list_item, items);`

The problem with this is that the Activity now have access to the Model and has a reference to an ArrayList of items which I wanted to keep only in the presenter and manage it from there.

I can't move setup the adapter on the Presenter because I would have to share the context from the Activity to the presenter, setup the adapter and pass it back to the Activity. The problem with this is that the presenter now depends on an Android context object (There shouldn't be any Android code in the Presenter part of an MVP Android project).

So the question is what do I do in this case? Where and how do I handle setting up the ArrayAdapter?

guipivoto
  • 18,327
  • 9
  • 60
  • 75
xlog
  • 103
  • 13
  • What's bad idea of `adapter` in `Presenter`. We clearly can't understand your problem? – Nick Bapu May 23 '19 at 12:18
  • To initialize the `ArrayAdapter`, an Android Activity `context` needs to be passed to its constructor. And as far as I'm aware, the `Presenter` should not contain any Android code. – xlog May 23 '19 at 12:21
  • 1
    You should have your presenter "Present" the `Collection` to the `View`. `MyAdapter` should not take a `Collection` as an argument, instead initiailise its own internal `Collection`. You should update `MyAdapter` from the view with a method on this class like `MyAdapter::update(List items)` which clears the in internal collection, adds all of the new updates and updates the dataset. Your Presenter should hold a reference to the model, with has your use cases - like getting data from a repository. Pseudo code maybe pointless here as you've not provided any code for context – Mark May 23 '19 at 12:23

2 Answers2

1
  1. I recommend you to use RecyclerView and not ListView for better performance.
  2. The activity can hold the RecyclerView, you should ask the presenter to fetch the data you want from your model repository, etc. After the presenter retrieved the data you should notify the Activity about the new data, and set it to the RecyclerAdapter. Now your activity holds inflates all regarding the view, and the presenter is a hub for data and logic.
Oren Zakay
  • 519
  • 8
  • 17
1

You can keep a list of items in the Presenter and then, send it to the Activity when you need to set up the adapter.

I think you can do:

Contract:

public interface ViewContract {
    void setupContentList(ArrayList<MyModel> list);
}

public interface PresenterContract {
    void onViewCreated();
}

Activity:

public class MainActivity extends Activity implements ViewContract {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ......
        mListView = findViewById(R.id.listview);
        mPresenter.onViewCreated();
    }

    public void setupContentList(ArrayList<MyModel> list) {
        MyAdapter adapter = new MyAdapter<MyModel>(this, R.layout.list_item, items);
        mListView.setAdapter(adapter);
    }
}

Presenter:

public class Presenter implements PresenterContract {

    public Presenter() {
        ArrayList<MyModel> mItems = new ArrayList();
        // Add items to the list
    }

    public void onViewCreated() {
        mView.setupContentList(mItems);
    }
}
guipivoto
  • 18,327
  • 9
  • 60
  • 75
  • Although I tried to strictly keep the View (Activity) and the Model separate, a simple reference to the Model in the Adapter constructor in the View can't hurt I think. – xlog May 23 '19 at 15:22
  • @FilipKowalczyk Model can be and should be shared between the View and the Presenter. I guess this does not hurt the MVP model. Model is your custom class.. it is not an Android class. So, you can share it between the View and the Presenter – guipivoto May 23 '19 at 15:25