Presenter Features

Cross-presenter Communication

In addition to decoupling application logic from UI, Robo MVP also help you remove strong references between UI stuffs, which is usually complicated and makes your application vulnerable to memory leak.

Robo MVP offers Message Bus for a better way of communication. In which, every presenter can communicate with each other without any strong references between them. Thus makes it very easy to add or remove UI components.

Message Bus is another product from Robo Creative. Its detailed information and brief instructions can be found here.
Sample

Defines a message that encapsulates a content of string similar to following snippet

package com.example.myapplication;

import com.robo.messaging.AbstractMessage;

public class MyMessage extends AbstractMessage<String> {

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

The presenter below acts as a publisher that publishes a message when the view becomes ready.

package com.example.myapplication;

import com.robo.mvp.AbstractPresenter;
import com.robo.mvp.View;

public class PublisherPresenter extends AbstractPresenter<View> {
    @Override
    protected void onViewSet(View view) {
        view.getListeners().set(View.OnReadyListener.class, new View.OnReadyListener() {
            @Override
            public void onReady() {
                mMessageBus.publish(new MyMessage("Hi there!"));
            }
        });
    }
}

In another presenter, subscribe to the message. The subscriber will receive message whenever a publisher publishes a MyMessage.

package com.example.myapplication;

import android.util.Log;

import com.robo.messaging.Subscriber;
import com.robo.mvp.AbstractPresenter;
import com.robo.mvp.View;

public class SubscriberPresenter extends AbstractPresenter<View> {
    @Override
    protected void onViewSet(View view) {
        mMessageBus.subscribe(new Subscriber<MyMessage>() {
            @Override
            public void receive(MyMessage message) {
                Log.d("Messaging", "Received message: " + message.getContent());
            }
        });
    }
}
Cancellation of Subscriptions

Message Bus automatically cancels all subscriptions made by a presenter when the presenter being destroyed, except the ones with keepSubscriberAlive = true. Meaning you don't need to manually cancel any subscription whose keepSubscriberAlive = false (default value).

The option keepSubscriberAlive is specially helpful in case you want to use a long-lived subscriber that receives messages during entire application life cycle and can only be cancelled manually by yourself. An example of this is the audit logger being intended for logging all messages out for debugging purpose. In splash screen, you subscribe the logger to the bus. When application exits, you cancel its subscription to release it.

Sample

The MessageLogger below intended for logging all messages among components. It implements Subscriber and accepts com.robo.messaging.Message - the top level interface so it will be able to receive messages of all types. Note that we are going to use it as a singleton component.

package com.example.myapplication;

import android.util.Log;

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

/**
 * Intended for logging all messages transferred among components in application.
 */
public class MessageLogger implements Subscriber<Message> {

    private static MessageLogger sInstance;

    private MessageLogger() {

    }

    /**
     * Creates and returns a singleton instance of this logger.
     */
    public static synchronized MessageLogger instance() {
        if (null == sInstance) {
            sInstance = new MessageLogger();
        }
        return sInstance;
    }

    @Override
    public void receive(Message message) {
        Log.d("Messaging", "Received message: " + message.getContent().toString());
    }
}

In presenter of the splash screen, subscribe the singleton MessageLogger to the bus. You might also notice that acceptsChildMessages, receiveHistoricMessages and keepSubscriberAlive are all set to True.

package com.example.myapplication;

import com.robo.messaging.ThreadOption;
import com.robo.mvp.AbstractPresenter;
import com.robo.mvp.View;

public class SplashPresenter extends AbstractPresenter<SplashView> {

    @Override
    protected void onViewSet(SplashView view) {
        /**
         * Subscribes the global logger so that it can receive all messages among components.
         * For the logging purpose, it's fine to use background thread with lowest priority to
         * reduce impacts to application performance.
         */
        mMessageBus.subscribe(MessageLogger.instance(), Integer.MAX_VALUE, true, true, ThreadOption.BACKGROUND, true);

        view.getListeners().set(View.OnReadyListener.class, new View.OnReadyListener() {
            @Override
            public void onReady() {
                // initializes components then navigates user to main screen when everything ready.
            }
        });
    }
}