How to monitor LiveData hasActiveObservers()?

Viewed 226

I have MyRepository that obtains a live feed from a server via a socket.

It provides its data to MyViewModel via a MutableLiveData object which can be observed from a Fragment.

To avoid wasting resources, I don't want MyRepository to be obtaining data from the server when there are no observers.

I'd like to know how to monitor MyRepository's MutableLiveData, so if there are no observers then MyRepository can stop retrieving data from the server. Similarly, if an observer is added, then data retrieval can (re)start.

Currently, I'm just using a basic Thread (see the createObserversMonitorThread() method) as the monitor:

public class MyRepository {

    private static final String TAG = MyRepository.class.getSimpleName();

    private MutableLiveData<String> mutableLiveData;
    
    private Socket mSocket = null;

    public MyRepository(Application application) {

        mutableLiveData = new MutableLiveData<>();

        createSocket();
        
        createObserversMonitorThread();
    }

    private void createObserversMonitorThread() {

        Thread thread = new Thread() {

            @Override
            public void run() {

                try {
                    while (isAlive()) {

                        if (mutableLiveData.hasActiveObservers()) {

                            // We have observers, so connect to the server.
                            if (!mSocket.connected()) {
                                mSocket.connect();
                            }
                        }
                        else {

                            // We don't have observers, so disconnect from the server.
                            if (mSocket.connected()) {
                                mSocket.disconnect();
                            }
                        }

                        // Wait until next loop.
                        Thread.sleep(1000);
                    }
                }
                catch(Exception e) {

                    Log.e(TAG, "Exception", e);
                }
            }
        };

        thread.setName("MutableLiveData Observers Monitor");
        thread.setPriority(1);
        thread.setDaemon(true);
        thread.start();
    }

    public LiveData<String> getMutableLiveData() {
        return mutableLiveData;
    }

    /**
     * This method posts retrieved data to mutableLiveData.
     */
    private void createSocket() {

        try {
            mSocket = IO.socket(Constants.SERVER_URL);
            mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {

                @Override
                public void call(Object... args) {

                    Log.d(TAG, "Connected.");
                }
            }).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {

                @Override
                public void call(Object... args) {

                    if (args[0] instanceof Exception) {
                        Log.e(TAG, "Connect error: ", (Exception)args[0]);
                    }
                    else {
                        Log.e(TAG, "Connect error: " + args[0]);
                    }
                }

            }).on(Socket.EVENT_RECONNECT, new Emitter.Listener() {

                @Override
                public void call(Object... args) {

                    Log.d(TAG, "Reconnected.");
                }
            }).on(Socket.EVENT_RECONNECT_ERROR, new Emitter.Listener() {

                @Override
                public void call(Object... args) {

                    if (args[0] instanceof Exception) {
                        Log.e(TAG, "Reconnect error: ", (Exception)args[0]);
                    }
                    else {
                        Log.e(TAG, "Reconnect error: " + args[0]);
                    }
                }

            }).on(Socket.EVENT_MESSAGE, new Emitter.Listener() {

                @Override
                public void call(Object... args) {

                    //Log.d(TAG, "Data received.");

                    String s = (String) args[0];
                    mutableLiveData.postValue(s);
                }

            }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {

                @Override
                public void call(Object... args) {
                    Log.d(TAG, "Disconnected.");
                }

            }).on(Socket.EVENT_ERROR, new Emitter.Listener() {

                @Override
                public void call(Object... args) {

                    if (args[0] instanceof Exception) {
                        Log.e(TAG, "Error: ", (Exception)args[0]);
                    }
                    else {
                        Log.e(TAG, "Error: " + args[0]);
                    }
                }

            });
        }
        catch(Exception e) {
            Log.e(TAG, "Could not create socket", e);
        }
    }
}

It works, but is there a better way?

UPDATE

Solution, thanks to EpicPandaForce's answer:

public class MyRepository {

    private static final String TAG = MyRepository.class.getSimpleName();

    private MutableLiveData<String> mutableLiveData;

    private Socket mSocket = null;

    public MyRepository(Application application) {

        createSocket();

        mutableLiveData = new MutableLiveData<String>() {

            @Override
            protected void onActive() {
                super.onActive();

                // Connect to server. This will (re)start data being posted on mutableLiveData.
                if (!mSocket.connected()) {
                    mSocket.connect();
                }
            }

            @Override
            protected void onInactive() {
                super.onInactive();

                // Disconnect from server. This will stop data being posted on mutableLiveData.
                if (mSocket.connected()) {
                    mSocket.disconnect();
                }
            }
        };
    }

    public LiveData<String> getMutableLiveData() {
        return mutableLiveData;
    }

    /**
     * This method posts retrieved data to mutableLiveData.
     */
    private void createSocket() {
        // Same code as before.
    }
}
1 Answers

You can use extends LiveData<T> or extends MutableLiveData<T> to get ahold of onActive() callback where you are notified if you have at least 1 active observer, and onInactive() callback when you went from 1 to 0 active observers.

That way you don't even need to ask for hasActiveObservers().

Related