Jesus Dimrix
Jesus Dimrix

Reputation: 4568

MVP Architecture Dilema about android classes

I have read about MVP and i saw many different implementations of it , so this is the 3 ground rules i follow that relevant to my question.

1 . The View will receive orders from the presenter only about Ui like showImage and will notify the presenter about Ui interactions like takePictureButtonPressed .

2 . The Presenter will hold the data and the logic of the application but will not touch the views , he will order the view to do so .

3 . The Presenter will not import any Android classes . I think we have decide about it for UnitTest reasons and an easy way to know you are implementing it right so in every project we have we will have a same implementation more or less .

My Question/Problem is in a scenario when we need to do an android stuff that are more complicated than just showImage

Example :

Lets say we want to take picture and show it inside image view and save the path for future logic in my application .

The button click -> The view will notify the presenter - > the presenter will tell the view the start camera - >

@Override
public void dispatchTakePictureIntent() {
        // Blah Blah Blah
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        mImagePath = photoFile.getAbsolutePath();
    }
} 

And when result is coming :

        mPresenter.profileImageReceived(mImagePath);

than i want to show the image , to show it we need to create Bitmap from the imagePath so i wrote a method inside ImageUtils that does it for me...so far so good .

Whats the problem ???

My method uses android classes so it can't be inside my presenter and The view is not suppose to do anything but to show stuff .

Where my android methods that are not related to the application logic should be ?

my current solution is to address the view as view handler and android helper so in my view i will convert the path to a Bitmap like this :

    @Override
    public void setProfileImage(String imagePath) {
        Bitmap bitmap = ImageUtils.getBitmapFromPath(imagePath);
        mPhotoImage.setImageBitmap(bitmap);
        bitmap.compress(Bitmap.CompressFormat.PNG,100,stream);
     }

other approach is to put :

        Bitmap bitmap = ImageUtils.getBitmapFromPath(imagePath);

inside the presenter i will pass the the bitmap ready to the view but in that way my presenter will do actions with android library which i don't want him to .

Another simpler example is in a case i want to show buttons of takeImage only if user has camera , so the presenter will need to know if the device has camera but the presenter not uses android in my approach so it will be like this :

    getView().showCameraComponents(getView().isCameraAvailable());   

so My view is handling views and act as an Android stuff helper for presenter

would you say it is good practice to do so ?

What is the best approach and why ?

Upvotes: 0

Views: 352

Answers (1)

Oleksii Dankov
Oleksii Dankov

Reputation: 46

In general, I suggest you to treat the View and Presente's functions as below.

View:

  • takes user input and actions and it pass to presenter (formdata, button click, taking photo is input as well)
  • does presenter orders

Presenter:

  • decide what to do with views input
  • give the order to view what to display

In addition, good way to avoid of using android components and very context related components is polymorphism.

Make an interfaces for different use cases and implement them wrapping the android components and etc. If the presenter, model or any other component require something related to app context you can work with interfaces and provide its implementation with dependency injection.

Small example (with dagger):

public interface CameraAvaialableDetector {
    boolean isCameraAvailable();
}

Presenter or interactor has field:

@Inject CameraAvaialableDetector mCameraAvailableDetector

With dependency injection you can provide it with any CameraAvaialableDetector implementation for example your fragment or mock for tests.

Upvotes: 1

Related Questions