Search code examples
androidmvpevent-busotto

Model View Presenter with an EventBus, how to get Events back to Presenter?


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?


Solution

  • 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
        }  
        }