androidobserver-patternotto

Otto event bus runtime subscription for events


Is it possible in Otto to subscribe to events without using @Subscribe annotation ?

In my use case I do not know to which event my object should subscribe to at compile time. I wish to do it at runtime based on certain rules.


Solution

  • I suppose you can use a workaround like this,

    public class MainClass {    
    
        private EventObserver eventObserver;
    
        public MainClass() {
            if(...someCondition...) {
                eventObserver = new FirstEventObserver();
            } else {
                eventObserver = new SecondEventObserver();
            }
        }
    
        public onEvent(Event event) {
            if (event instanceOf FirstEvent) {
                ... handle event ...
            } else if (event instanceOf SecondEvent) {
                ... handle event ...
            }
        }
    }
    
    public abstract class EventObserver {
    
        protected MainClass mainClass;
    
        public void setMainClass(MainClass mainClass) {
            this.mainClass = mainClass;
        }
    
        protected void notifyMainClass(Event event) {
            if (mainClass != null) {
                mainClass.onEvent(event);
            }
        }
    }
    
    public class FirstEventObserver extends EventObserver {
    
        public FirstEventObserver() {
            bus.subscribe(this);
        }
    
        @Subscribe
        public void onEvent(FirstEvent event) {
            notifyMainClass();
        }
    }
    
    
    public class SecondEventObserver extends EventObserver {
    
        public SecondEventObserver() {
            bus.subscribe(this);
        }
    
        @Subscribe
        public void onEvent(SecondEvent event) {
            notifyMainClass();
        }
    }
    
    public abstract class Event {
    }
    
    public abstract class FirstEvent extends Event {
    }
    
    public abstract class SecondEvent extends Event {
    }
    

    Another workaround, which is a much cleaner solution. You can generate the event at runtime with the type you want.

    public class MainClass {
        @Subscribe
        public void onEvent(Event event) {
            if (event.getType() == EventType.FIRST_EVENT) {
                ... handle event ...
            } else if (event.getType() == EventType.SECOND_EVENT) {
                ... handle event ...
            }
        }
    }
    
    public class Event {
        public enum EventType {
            FIRST_EVENT,
            SECOND_EVENT
        }
    
        private EventType eventType;
    
        public Event(EventType eventType) {
            this.eventType = eventType;
        }
    
        public EventType getType() {
            return eventType;
        }
    }