17

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.

Originerd
  • 694
  • 1
  • 6
  • 12
  • 1
    There seems to be a lot of confusion about MVP in the Android world. The Activity (or Fragment etc) is the "V" in MVP, not the "P". See: http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/ and http://saulmm.github.io/2015/02/02/A%20useful%20stack%20on%20android%20%231,%20architecture/ – G. Lombard Mar 16 '15 at 03:39
  • @G.Lombard, now it's http://saulmm.github.io/2015/02/02/A-useful-stack-on-android-1,-architecture/. – CoolMind Jun 05 '16 at 18:32

3 Answers3

6

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.

albertovecina
  • 93
  • 1
  • 4
2

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.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • 6
    I don't think so. MVP, MVC are architectural pattern, and adapter is design pattern. They should not be the same. See discussions http://stackoverflow.com/a/4243407/3304280 – Cheng Nov 18 '16 at 16:49
  • You act like there's a difference between design and architecture. There isn't, they're synonyms – Gabe Sechan Nov 18 '16 at 18:02
  • no, they are not synonyms, design patterns are basically using object-oriented software development to solve problems and make code or pattern reusable, while architecture patterns are aiming to deal with the whole structure of the application. They are definitely different. Your answer is misleading and wrong. – Cheng Nov 18 '16 at 21:28
  • 16 years in the Fields, they've been used as synonyms since the beginning. Sorry, you're just wrong here – Gabe Sechan Nov 18 '16 at 21:30
  • even that doesn't convince me https://www.oreilly.com/ideas/contrasting-architecture-patterns-with-design-patterns – Cheng Nov 18 '16 at 21:38
  • An mvp pattern is a pattern where you have a data model (say a list item), an output format (generally but not always graphical like a view hierarchy), and a class that takes the model and changes the view to reflect it. Which is exactly what a list view adapter does. So it is absolutely mvp. If you're saying it isn't them you don't understand what mvp is. Here's some reading https://en.m.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter – Gabe Sechan Nov 18 '16 at 22:38
  • As for your idea of a design pattern being different- younger just wrong. Mvp and mvc are even written about as design patterns in the gang of 4 book on design patterns. Not that I agree with you that there's a difference between the two. – Gabe Sechan Nov 18 '16 at 22:40
  • Nor does showing an oreiley book mean anything. Appeal top authority it's a logical fallacy. If you want to argue, show why a list view adapter does not fit the p in mvp. Otherwise you have no point – Gabe Sechan Nov 18 '16 at 22:43
  • 1
    Adapter is part of V in MVP. First, it is part of Android library, when in P the only thing you want to do with Android library classes is optionally receive them as parameters, this way you can later easly mock them while unit testing. Second, adapter has methods for creating and displaying layout items, while in P you shouldn't think about displaying data, but about controlling it. Answer below, provided by @albertovecina should be accepted instead. – Darek Deoniziak Dec 08 '16 at 19:14
  • @DarekDeoniziak Because it creates the view it can't be a presenter? Who the hell do you think does? The view can't create itself. The model can't create it, that's the worst place in the world to put the view creation logic. The P always creates the view, in any MVP model. You might create them automagically through some factory interface for mocking, but its still the presenter that ends up creating them. And no, the adapter has no functionality for drawing of views. Calling a class that sets all the values from a model like an adapter part of the view is just wrong. – Gabe Sechan Dec 08 '16 at 19:28
  • @Gabe Sechan It depends what decision about implementation is taken, there are 3 options, V can be created in P, P can be created in V (then V will be passed to P) or there will be 3rd object managing all. By display I meant adapter can control views, wrote something else when I was thinking about another, my bad and after second thought this can be job of P too. P is here to separate logic, but when you additionaly want to separate P from Android, you can't use adapters as P, it makes P impossible to test in junit. If adapter shouldn't be able to manipulate data, then that's another P job. – Darek Deoniziak Dec 09 '16 at 22:40
  • 1
    @DarekDeoniziak You have way too specific idea of what MVP is. What your describing is one specific implementation of MVP. IN general, MVP requires a data object(s), separate view object(s), and a presenter object that manipulates the view in order to display the data. THat's all it takes. It has nothing to do with unit tests, junit or otherwise. – Gabe Sechan Dec 09 '16 at 22:47
  • @Gabe Sechan Often all parts of Android framework are treated as V, it improves testability, that's why I did mention it. Adapter has role of adapting data to views, that should be the only adapter responsibility. Another, separate P object for getting data from model is needed, same about handling actions from list items. That's how I see it, but I think now it doesn't conflict to call adapter a P too. Thank you for clearing it out. Also found this (I don't think class name here is coincidence): https://developer.android.com/reference/android/support/v17/leanback/widget/Presenter.html – Darek Deoniziak Dec 10 '16 at 09:20
1

If there is only a listview in that activity then there is no need to write a separate presenter because Adapter is actually working as Presenter for ListView. But if you have other UI components than ListView that need to be updated then you must need to write a separate Presenter for those UI components.

Yasir Ali
  • 1,785
  • 1
  • 16
  • 21