Android Open Source - droidkit-engines Notification Center






From Project

Back to project page droidkit-engines.

License

The source code is released under:

MIT License

If you think the Android project droidkit-engines listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.droidkit.engine.event;
//  w w w  .  j a  va  2 s.  com
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;

import com.droidkit.actors.dispatch.RunnableDispatcher;
import com.droidkit.engine.Engines;
import com.droidkit.engine._internal.util.Utils;
import com.droidkit.engine._internal.util.WeakEqualReference;

import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class NotificationCenter {

    static {
        Engines.init();
    }

    private static final String KEY_DELIMITER = "-";

    private static final String TAG = "NotificationCenter";

    private static final int NO_ID = Integer.MIN_VALUE;

    private volatile static NotificationCenter instance;

    public static NotificationCenter getInstance() {
        if (instance == null) {
            synchronized (NotificationCenter.class) {
                if (instance == null) {
                    instance = new NotificationCenter();
                }
            }
        }
        return instance;
    }

    @SuppressLint("NewApi")
    private NotificationCenter() {
        backgroundFireLoop = new RunnableDispatcher(1);

        listeners = Collections.newSetFromMap(new ConcurrentHashMap<WeakEqualReference<OnNotificationListenerContainer>, Boolean>());

        states = new ConcurrentHashMap<Integer, State>();

        statesValues = new ConcurrentHashMap<String, Object[]>();
    }

/////////////////////////////////////////////////////////////////////////////////////////////////////

    private final Handler handler = new Handler(Looper.getMainLooper());

    private final Object fireRemoveSyncObject = new Object();

    /**
     * Loop for background event fires
     */
    private final RunnableDispatcher backgroundFireLoop;

    /**
     * Active listeners storage
     */
    private final Set<WeakEqualReference<OnNotificationListenerContainer>> listeners;

    /**
     * States storage
     */
    private final ConcurrentHashMap<Integer, State> states;

    /**
     * States values in-memory storage
     */
    private final ConcurrentHashMap<String, Object[]> statesValues;


/////////////////////////////////////////////////////////////////////////////////////////////////////

    public State registerState(final int eventType, final StateInitValue stateInitValue) {
        final State state = new State(eventType, stateInitValue);
        states.put(eventType, state);
        return state;
    }

    /**
     * Add new listener for specified eventType and eventId
     * You must keep a strong reference to your listener somewhere to prevent GC from removing it from memory
     *
     * @param eventType
     * @param eventId
     * @param notificationListener
     */
    public void addListener(int eventType, int eventId, NotificationListener notificationListener) {
        final State state = states.get(eventType);
        if (state != null) {
            Object[] value = statesValues.get(getKeyForEvent(eventType, eventId));

            if (value == null && state.getStateInitValue() != null) {
                value = state.getStateInitValue().initState(eventType, eventId);
            }

            if (notificationListener != null) {
                notificationListener.onNotification(eventType, eventId, value);
            }
        }

        if (notificationListener != null) {
            listeners.add(new WeakEqualReference<OnNotificationListenerContainer>(
                    new OnNotificationListenerContainer(eventType, eventId, notificationListener, Utils.isUIThread())
            ));
        }
    }

    /**
     * The same addListener(int, int, NotificationListener), but with eventId == NO_ID
     *
     * @param eventType
     * @param notificationListener
     */
    public void addListener(int eventType, NotificationListener notificationListener) {
        addListener(eventType, NO_ID, notificationListener);
    }

    public void removeListener(NotificationListener notificationListener) {

        final Iterator<WeakEqualReference<OnNotificationListenerContainer>> it = listeners.iterator();

        while (it.hasNext()) {
            final WeakEqualReference<OnNotificationListenerContainer> weakListenerContainer = it.next();
            final OnNotificationListenerContainer listenerContainer = weakListenerContainer.get();
            if (listenerContainer == null) {
                it.remove();
            } else if (listenerContainer.listener == notificationListener) {
                synchronized (fireRemoveSyncObject) {
                    it.remove();
                    listenerContainer.setDeleted(true);
                }
                //continue iterate after that, because we can have the same NotificationListener
                //for different eventType and eventId parameters
            }
        }
    }

    public void fireEvent(final int eventType, final int eventId, final Object[] args) {
        final Iterator<WeakEqualReference<OnNotificationListenerContainer>> it = listeners.iterator();

        final boolean isUiThread = Utils.isUIThread();

        final State state = states.get(eventType);
        if (state != null) {
            statesValues.put(getKeyForEvent(eventType, eventId), args);
        }
        while (it.hasNext()) {
            final WeakEqualReference<OnNotificationListenerContainer> weakListenerContainer = it.next();
            final OnNotificationListenerContainer listenerContainer = weakListenerContainer.get();

            if (listenerContainer == null) {
                it.remove();
            } else if (listenerContainer.eventType == eventType && listenerContainer.eventId == eventId) {

                synchronized (fireRemoveSyncObject) {
                    if (!listenerContainer.isDeleted()) {
                        if (isUiThread && listenerContainer.wasAddedInUIThread) {
                            listenerContainer.listener.onNotification(eventType, eventId, args);
                            continue;
                        }
                        final Runnable fireEvent = new Runnable() {
                            @Override
                            public void run() {
                                synchronized (fireRemoveSyncObject) {
                                    //double-check here
                                    if (!listenerContainer.isDeleted()) {
                                        listenerContainer.listener.onNotification(eventType, eventId, args);
                                    }
                                }
                            }
                        };
                        if (listenerContainer.wasAddedInUIThread) {
                            handler.post(fireEvent);
                        } else {
                            backgroundFireLoop.postAction(fireEvent);
                        }
                    }
                }
            }
        }
    }

    /**
     * The same as fireEvent(int, int, Object[]), but with args == null
     *
     * @param eventType
     * @param eventId
     */
    public void fireEvent(final int eventType, final int eventId) {
        fireEvent(eventType, eventId, null);
    }

    /**
     * The same as fireEvent(int, int, Object[]), but with eventId == NO_ID
     *
     * @param eventType
     * @param args
     */
    public void fireEvent(final int eventType, final Object[] args) {
        fireEvent(eventType, NO_ID, args);
    }

    /**
     * The same as fireEvent(int, int, Object[]), but with args == null and eventId == NO_ID
     *
     * @param eventType
     */
    public void fireEvent(final int eventType) {
        fireEvent(eventType, NO_ID, null);
    }

    private String getKeyForEvent(final int eventType, final int eventId) {
        return eventType + KEY_DELIMITER + eventId;
    }

    /**
     * Container to store NotificationListener in listener's container
     */
    private class OnNotificationListenerContainer {
        int eventType;
        int eventId;
        NotificationListener listener;
        boolean wasAddedInUIThread;
        volatile boolean deleted = false;

        private OnNotificationListenerContainer(int eventType, int eventId,
                                                NotificationListener listener, boolean wasAddedInUIThread) {
            this.eventType = eventType;
            this.eventId = eventId;
            this.listener = listener;
            this.wasAddedInUIThread = wasAddedInUIThread;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            OnNotificationListenerContainer that = (OnNotificationListenerContainer) o;

            if (eventId != that.eventId) return false;
            if (eventType != that.eventType) return false;
            if (!listener.equals(that.listener)) return false;

            return true;
        }

        @Override
        public int hashCode() {
            int result = eventType;
            result = 31 * result + eventId;
            result = 31 * result + listener.hashCode();
            return result;
        }

        @Override
        public String toString() {
            return "OnNotificationListenerContainer{" +
                    "eventType=" + eventType +
                    ", eventId=" + eventId +
                    ", listener=" + listener +
                    '}';
        }

        public boolean isDeleted() {
            return deleted;
        }

        public void setDeleted(final boolean deleted) {
            this.deleted = deleted;
        }
    }
}




Java Source Code List

com.droidkit.engine.Engines.java
com.droidkit.engine.common.KeyCallback.java
com.droidkit.engine.common.ValueCallback.java
com.droidkit.engine.common.ValuesCallback.java
com.droidkit.engine.event.Events.java
com.droidkit.engine.event.NotificationCenter.java
com.droidkit.engine.event.NotificationListener.java
com.droidkit.engine.event.StateInitValue.java
com.droidkit.engine.event.State.java
com.droidkit.engine._internal.RunnableActor.java
com.droidkit.engine._internal.sqlite.AbstractDao.java
com.droidkit.engine._internal.sqlite.BinarySerializator.java
com.droidkit.engine._internal.sqlite.DbHelper.java
com.droidkit.engine._internal.sqlite.DbProvider.java
com.droidkit.engine._internal.sqlite.FastCursor.java
com.droidkit.engine._internal.sqlite.SqlStatements.java
com.droidkit.engine._internal.util.SortedArrayList.java
com.droidkit.engine._internal.util.Utils.java
com.droidkit.engine._internal.util.WeakEqualReference.java
com.droidkit.engine.keyvalue.DataAdapter.java
com.droidkit.engine.keyvalue.KeyValueEngine.java
com.droidkit.engine.keyvalue.StorageAdapter.java
com.droidkit.engine.keyvalue.sqlite.SQLiteStorageAdapter.java
com.droidkit.engine.keyvalue.sqlite.internal.KeyValueEngineDao.java
com.droidkit.engine.keyvalue.sqlite.internal.KeyValueEngineTableStatements.java
com.droidkit.engine.list.DataAdapter.java
com.droidkit.engine.list.ListEngine.java
com.droidkit.engine.list.StorageAdapter.java
com.droidkit.engine.list.sqlite.SQLiteMultipleStorageAdapter.java
com.droidkit.engine.list.sqlite.SQLiteStorageAdapter.java
com.droidkit.engine.list.sqlite.internal.ListEngineDao.java
com.droidkit.engine.list.sqlite.internal.ListEngineTableStatements.java
com.droidkit.sample.ActivityHelper.java
com.droidkit.sample.BaseActivity.java
com.droidkit.sample.TestMainActivity.java
com.droidkit.sample.listenginetest.TestListEngineActivity.java
com.droidkit.sample.listenginetest.TestProto.java
com.droidkit.sample.view.BlockingListView.java