Subscription Options

Default Options

Use this shortest method to subscribe to the bus with all default options. In which:

  • Priority is zero.
  • Child messages are also accepted.
  • No historic messages.
  • Messages are delivered by publisher’s thread.
  • Message Bus maintains a weak reference to subscriber.
Sample
package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;

public class MySubscriber {

    private MessageBus mMessageBus;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribe() {
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received message: " + message.getContent());
            }
        });
    }
}

Subscription Priority

Use this option to specify priority of subscriber. The lower number, the higher priority. The higher priority, the sooner the subscriber receives messages than the other. Default is zero.

Sample
package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;

public class MySubscriber {

    private MessageBus mMessageBus;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribeWithPriority() {
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received first");
            }
        }, 0); // lower number, higher priority.

        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received last");
            }
        }, 1); // lower priority than the subscriber above.
    }
}

Receiving Child Messages

Use this option to specify whether the subscriber accepts messages which derivate from the subscribed message type or not. Default is true.

Sample

Create a child message as derivative of MyMessage as below:

package com.example.myapplication;

public class MyChildMessage extends MyMessage {

    protected MyChildMessage(String content) {
        super(content);
    }
}

In the subscriber, subscribe to MyMessage with both options: accepting child messages and not.

package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;

public class MySubscriber {

    private MessageBus mMessageBus;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribeWithChildMessages() {
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage myMessage) {
                Log.d("MessageBus", "Received message: " + myMessage.getContent());
            }
        }); // default is true, accepts child messages.

        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                throw new IllegalStateException("This message should not be received");
            }
        }, 0, false); // false => refuses child messages.
    }
}

Now let the publisher publish a message of MyChildMessage:

package com.example.myapplication;

import com.robo.messaging.MessageBus;

public class MyPublisher {

    private MessageBus mMessageBus;

    public MyPublisher(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doPublishChildMessage() {
        mMessageBus.publish(new MyChildMessage("The child message"));
    }
}

Receiving Historic Messages

Use this option to specify whether the subscriber also receives historic messages or not. Default is false.

Sample

First, let the publisher publish a message with the option to keep the message in history after sending.

package com.example.myapplication;

import com.robo.messaging.MessageBus;

public class MyPublisher {

    private MessageBus mMessageBus;

    public MyPublisher(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doPublishAndKeepInHistory() {
        // keep message in history by setting second param to true.
        mMessageBus.publish(new MyMessage("Published and kept in history"), true);
    }
}

Then, let subscriber subscribe to the message with the option to receive historic messages.

package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;

public class MySubscriber {

    private MessageBus mMessageBus;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribeHistoricMessages() {
        // subscribes with option to receive historic messages.
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received message: " + message.getContent());
                // you can remove the message from history after receiving
                mMessageBus.remove(message);
            }
        }, 0, false, true); // true => receives historic messages.

        // you can also clear all messages in history if necessary
        mMessageBus.clearHistory();
    }
}

The final execution code looks like following snippet. Note that the publisher publishes message before the subscriber subscribing.

MessageBus messageBus = new MessageBusImp();

MyPublisher publisher = new MyPublisher(messageBus);
publisher.doPublishAndKeepInHistory("Hello world!");

MySubscriber subscriber = new MySubscriber(messageBus);
subscriber.doSubscribeHistoricMessages();

Specifying Delivery Thread

Use this option to specify thread used for delivering messages. In which:

  • Publisher: Publisher’s thread will be used to deliver messages.
  • Background: A different thread than subscriber's thread will be used to deliver messages.
  • UI: The main UI thread will be used to deliver messages.
Sample
package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;
import com.robo.messaging.ThreadOption;

public class MySubscriber {

    private MessageBus mMessageBus;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribeUsingPublisherThread() {
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received message from publisher's thread");
            }
        }, 0, false, true, ThreadOption.PUBLISHER); // default is PUBLISHER already.
    }

    public void doSubscribeUsingBackgroundThread() {
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received message from background thread");
            }
        }, 0, false, true, ThreadOption.BACKGROUND); // use different thread to subscriber's.
    }

    public void doSubscribeUsingUIThread() {
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received message from UI thread");
            }
        }, 0, false, true, ThreadOption.UI); // use main UI thread to deliver messages.
    }
}

Now just let publisher publish a message as usual. No more complex code logic required. Message Bus will take care of the delivery.

package com.example.myapplication;

import com.robo.messaging.MessageBus;

public class MyPublisher {

    private MessageBus mMessageBus;

    public MyPublisher(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doPublish(String content) {
        mMessageBus.publish(new MyMessage(content));
    }
}

Custom Delivery Strategy

Message Bus allows you to use your custom strategy to deliver messages beyond three built-in options as above. You can make your own strategy by implementing the interface PublishingStrategy as in example below:
package com.example.myapplication;

import com.robo.messaging.Message;
import com.robo.messaging.PublishingStrategy;
import com.robo.messaging.Subscriber;

public class MyDeliveryStrategy<TMessage extends Message> implements PublishingStrategy<TMessage> {

    @Override
    public void deliverMessage(Subscriber<TMessage> subscriber, TMessage message) {
        // your custom delivery logic here...
    }
}

In your subscriber, use your strategy instead of ThreadOption:

package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.Message;
import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;

public class MySubscriber {

    private MessageBus mMessageBus;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribeUsingCustomStrategy() {
        mMessageBus.subscribe(new Subscriber<Message>) {
            @Override
            public void receive(Message message) {
                Log.d("MessageBus", "Received via my own strategy");
            }
        }, 0, true, false, new MyDeliveryStrategy<Message>(), false);
    }
}

Keeping Subscriber Alive

Use this option to specify whether the Message Bus maintains a strong reference to the subscriber or not. Default is false.

Theoretically, a weak-referenced subscriber does not need manual cancellation of subscription. When the subscriber is collected by GC, its subscription will be automatically removed from the bus. However, it's strongly recommended to always manually cancel subscription when no longer needed.
Sample
package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;
import com.robo.messaging.ThreadOption;
import com.robo.messaging.SubscriptionToken;

public class MySubscriber {

    private MessageBus mMessageBus;
    private Subscriber<MyMessage> mSubscriber;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribeWithKeepingSubscribeAlive() {

        mSubscriber = new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received message: " + message.getContent());
            }
        };

        // maintains a strong reference to subscriber. The last parameter is the thing.
        mSubscriptionToken = mMessageBus.subscribe(mSubscriber, 0, false, true, ThreadOption.PUBLISHER, true);
    }

    public void unsubscribe() {
        // you also need to manually cancel the subscription of this strong-referenced subscriber.
        // we strongly recommend you to manually cancel subscription of both strong-referenced and
        // weak-referenced subscribers, as we don't know exactly when the GC actually collects the
        // weak-referenced subscribers. Keeping subscription for a destroyed subscriber might lead
        // to weird application behaviors.
        mMessageBus.unsubscribe(mSubscriptionToken);
    }
}

Cancelling a Subscription

To cancel a subscription of a subscriber, use method unsubscribe() with the SubscriptionToken retrieved from subscribing the subscriber before.

Sample
package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.MessageBus;
import com.robo.messaging.Subscriber;
import com.robo.messaging.SubscriptionToken;

public class MySubscriber {

    private MessageBus mMessageBus;
    private SubscriptionToken mSubscriptionToken;

    public MySubscriber(MessageBus messageBus) {
        mMessageBus = messageBus;
    }

    public void doSubscribe() {
        // keeps the subscription token for cancellation later on.
        mSubscriptionToken = mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("MessageBus", "Received message: " + message.getContent());
            }
        });
    }

    public void doUnsubscribe() {
        // uses the token to cancel subscription.
        mMessageBus.unsubscribe(mSubscriptionToken);
    }
}