GCX-HCI / ThirtyInch

a MVP library for Android favoring a stateful Presenter
Apache License 2.0
1.03k stars 101 forks source link

Initializing presenter state from intent #38

Closed dave08 closed 8 years ago

dave08 commented 8 years ago

If I receive an intent in my activity that should initialize it's state, how do I pass this to my presenter? Shouldn't onCreate in the presenter receive this intent? Or maybe there's a better way?

By the way, thanks for the great library, I've found it the best one I've tried (out of a whole bunch..).

jreehuis commented 8 years ago

It is a good practice in the MVP pattern to leave the Presenter plain old Java as much as possible. It makes it much easier to test the presenter without the need of Android Tests or Robolectric for example.

If you just want to initialize the presenter with the data, you could read the intent by getIntent() in the providePresenter() of the Activity and pass the data into the Presenter's Constructor. If you want to "update" the presenter data by Intent data, provide a method in the presenter for it and call it with the data e.g. in onCreate().

passsy commented 8 years ago

This is from the sample project:

    @NonNull
    @Override
    public AddEditTaskPresenter providePresenter() {
        final String taskId = getIntent()
                .getStringExtra(AddEditTaskActivity.ARGUMENT_EDIT_TASK_ID);
        final TasksRepository tasksRepository = Injection
                .provideTasksRepository(getApplicationContext());

        return new AddEditTaskPresenter(taskId, tasksRepository);
    }
dave08 commented 8 years ago

Thank you, that is a good idea, but since I'm using dagger2 for presenter dependencies, I had to use:

@Inject Provider<MyPresenter> presenterFactory

then I used the graph to inject it in providePresenter method. The dependecies are passed by injecting the presenter's constructor for ease of testing. So in the end I had to make a setter method on the presenter to set the state on the activity's onCreate. Am I doing this right? I thought it was wrong for the activity to do any actions, it should only be a 'passive' view displayer?

Thanks for all your answers!

passsy commented 8 years ago

I never use dagger to inject the presenter. I don't think it's useful. You never exchange the presenter with a mock implementation when doing tests. So my Activities and Presenters are hardcoded glued together. On the other hand using Dagger to inject dependnecies inside you presenter could be useful. If you're starting a new project consider building your app with constructor injection instead of dagger. It's often easier and has a good separation; inject android dependencies in your Activity and mock dependencies in your tests.

On android the passive view is often not possible. It is possible for your view implementation but the Activity has functionality which goes beyond the functionality of a view. Initialising the presenter, starting other Activities and handle the ActivityResult are things which aren't view related. But there is no other way to do it on Android 😞.

Don't over engineer and get things done in a testable way where it is testable, that's probably my best tip ✌️