4

I'm about creating a simple app with MVP implementation, and trying to make a permission request in a presenter. To make a permission request, I need to pass Context like this.

        // Location permission has not been granted yet, request it.
        ActivityCompat.requestPermissions(fragmentActivity, new String[]{permission}, requestId);

I've read several articles and they mention that using Context in a presenter is not a good exercise. So, I'm just wondering how people are handling a permission request with MVP. And I don't really know why using Context in a presenter is not good practice. Please, help me to understand how I should handle a permission request and why using context is not good practice.

Thanks

swordartist
  • 302
  • 2
  • 3
  • 8

2 Answers2

4

You must never send any object related to Android to the presenter layer, and they must be fully decoupled.

to do these things I always remember a good sentence and that goes Do not inject objects, inject operations and behavior.

it so simple dont inject your context into your presenter which is a wrong practice. instead in your view contract (view interface) add a function called getPermission() then in your view implement that method along with other methods of your contract, then call that method whenever you need the permission.

thats the best way. trust me ;)

Amir Ziarati
  • 14,248
  • 11
  • 47
  • 52
  • Thanks for replying Amir. So, other context required methods like getResource should be in view(Activity or Fragment) side, right? Now, I have other line in my presenter that is getting string array from strings.xml resource. But without contest, I cannot get string resources and cannot create string. In that case what do you do? – swordartist May 02 '17 at 21:01
  • How about when you open an external app from presenter with context.startActivity(intent) ? I was passing a context from view to my presenter and do context.startActivity(intent). – swordartist May 02 '17 at 22:42
  • 1
    look its so easy. every little thing can be done through interfaces. create an interface containing `startSomeActivity()` and `getSomeString()` in your presenter layer then implement these in your view layer then send the implementation to the pesenter. then presenter will triiger the actions whenever it needs to. – Amir Ziarati May 03 '17 at 04:10
  • Yes, it's easy, whenever you need to use Context let View do the work. But I was trying to give more clear role to view and presenter. View is just displaying what presenter says. So, what I'm doing is.. Presenter get data from model layer and/or resource. Then the presenter creates strings to display. Finally, presenter pass those strings to view layer. – swordartist May 04 '17 at 20:17
  • if its a message to show the status pf application like "error happened !" or "connection error !" it should be in resources in view layaer and there must be some methods like `showConnectionError()` which view implements. but for other strings like what you get from database the source of string is model and then presenter to the view ;) – Amir Ziarati May 06 '17 at 03:38
1

There are multiple flavors of MVP out there in practice. I am not here to start a debate which one is right and which one is wrong. As long as a particular flavor works for your scenario, it shall be used.

Instead, I will try to explain why the context in Presenter should be avoided and one of the ways I have avoided in my code.

One of the major reason you should not have a context in the presenter, there might be references to presenter which could leak the activity. In places where I had to deal with a context within the activity, I have accessed through Views.

interface View {
   Context getContext();
}

interface Presenter {
   void setView(View view);
}

So PresenterImpl implements a view, onCreate of the activity and resets it onDestroy of the activity. So the presenter never directly holds the context. But it holds the view, which has knowledge about the View.

Meghal Shah
  • 405
  • 2
  • 11