4

I am using the Model-View-Presenter design pattern coupled with an EventBus (Otto). The entire reason I implemented this pattern is to decouple events to the presenter only, and have the presenter update the views.

This is an example of some of the code I have, I'll use getting Events as an example. (Please note that Events is different from the EventBus Event, meaning an Event in Events is an event like "Dad's Birthday", but an Event in the EventBus is a Bus-event).

Fragment

public class EventFragment extends Fragment {

    private EventPresenter mEventPresenter;

    // Initialize boilerplate code...

    private void init() {
        mEventPresenter = new EventPresenter();
        mEventPresenter.loadEvents();
    }

    // I WANT TO MOVE THESE SUBSCRIPTION METHODS TO
    // MY PRESENTER OR SUBSCRIBER, BUT THEY ARE 
    // COUPLED TO THE ADAPTER OR A VIEW

    @Subscribe
    public void onEventsLoaded(EventsLoaded eventsLoaded) {
        List<Event> events = eventsLoaded.getEvents();
        mAdapter.setEvents(events);
    }

    @Subscribe
    public void onEventJoined(EventJoined eventJoined) {
        mItemView.doAnimation();
        mTextView.setText("Leave");
        mAdapter.joinEvent(eventJoined.getEvent());
    }

    @Subscribe
    public void onLeaveEvent(LeftEvent leftEvent) {
        mItemView.doAnimation();
        mTextView.setText("Join");
        mAdapter.leftEvent(leftEvent.getEvent());
    }

}

Presenter

public class EventPresenter {

    // This is the only method I have right now kind of defeats the purpose of 
    // having a presenter
    public void loadEvents() {
        EventBus.getInstance().post(new LoadEvents());
    }

}

Subscriber

public class EventSubscriber extends Subscriber {

    // This class is registered on the event bus

    @Subscribe
    public void onLoadEvents(LoadEvents loadEvents) {
        sClient.getEvents(new Callback<List<Event>>() {
              @Override
              public void onSuccess(List<Event> events, Response response) {
                   EventBus.post(new EventsLoaded(events));
              }

              @Override
              public void onFailure(.....) {
                    // Handle failure
              }
          };
    }
}

How can I get the Presenters and the Subscribers to handle all the business logic, and have the Fragment only handle views?

AndyRoid
  • 5,062
  • 8
  • 38
  • 73
  • may be subscribing events in presenter , with an instance of view inside it can help. Like presenter gets events from eventbus and call appropriate view method to update the UI. – MohK Aug 22 '15 at 06:07
  • Can you post an example answer? – AndyRoid Aug 22 '15 at 06:17

2 Answers2

5

This is not the best possibility but May Be help you out.

subscribing events in presenter , with an instance of view inside it can help. Like presenter gets events from eventbus and call appropriate view method to update the UI.

Mind that I have not changed method names of your fragment that updates UI and have passed event object directly from presenter which is indeed now a subscriber of events of eventbus. You can change it accordingly.

Fragment---

public class EventFragment extends Fragment {

    private EventPresenter mEventPresenter;

    // Initialize boilerplate code...

    @Override
    public void onResume()
    {
         mEventPresenter.onResume();
    } 

    @Override
    public void onPause()
    {
         mEventPresenter.onPause();
    }  

    private void init() {
        mEventPresenter = new EventPresenter(this);
        mEventPresenter.loadEvents();
    }

    // I WANT TO MOVE THESE SUBSCRIPTION METHODS TO
    // MY PRESENTER OR SUBSCRIBER, BUT THEY ARE 
    // COUPLED TO THE ADAPTER OR A VIEW

    public void onEventsLoaded(EventsLoaded eventsLoaded) {
        List<Event> events = eventsLoaded.getEvents();
        mAdapter.setEvents(events);
    }

    public void onEventJoined(EventJoined eventJoined) {
        mItemView.doAnimation();
        mTextView.setText("Leave");
        mAdapter.joinEvent(eventJoined.getEvent());
    }

    public void onLeaveEvent(LeftEvent leftEvent) {
        mItemView.doAnimation();
        mTextView.setText("Join");
        mAdapter.leftEvent(leftEvent.getEvent());
    }

}

Presenter----

    public class EventPresenter {
        private EventFragment targetView; 
        public EventPresenter(EventFragment myView)
        {
             targetView = myView;

        }
        // This is the only method I have right now kind of defeats the purpose of 
        // having a presenter
        public void loadEvents() {
            EventBus.getInstance().post(new LoadEvents());
        }

    @Subscribe
    public void onEventsLoaded(EventsLoaded eventsLoaded) {
        targetView.onEventsLoaded(eventsLoaded);
    }

    @Subscribe
    public void onEventJoined(EventJoined eventJoined) {
        targetView.onEventJoined(eventJoined);
    }

    @Subscribe
    public void onLeaveEvent(LeftEvent leftEvent) {
        targetView.onLeaveEvent(leftEvent);
    }


    public void onResume()
    {
         //subscride event bus
    } 


    public void onPause()
    {
         //unsubscride event bus
    }  
    }
MohK
  • 1,873
  • 1
  • 18
  • 29
  • Thanks for posting this answer, how would you handle something like fragment lifecycle methods? Or prevent an Activity from leaking when passed into the Presenter? – AndyRoid Aug 22 '15 at 06:46
  • Also how would you unsubscribe the eventbus in the presenter? – AndyRoid Aug 22 '15 at 07:03
  • 1
    My guess is that in the lifecycle method where the fragment or activity hits onPause or onDestroy, call a similar method in the presenter and unregister the bus, or set the target to null! Update your answer to include that and I'll accept your answer. – AndyRoid Aug 22 '15 at 07:10
4

This is responsability to presenters to send or receive events and after to notify fragment or activities

fab
  • 790
  • 6
  • 10