16

Android 中是否有相当于 iOS 类 NSNotificationCenter 的东西?是否有任何库或有用的代码可供我使用?

4

5 回答 5

21

在 Android 中,没有像 ios 中那样的中央通知中心。但是你基本上可以使用ObservableObserver对象来完成你的任务。

您可以像下面这样定义一个类,只需修改它以供单例使用并添加同步以供并发使用,但想法是相同的:

public class ObservingService {
    HashMap<String, Observable> observables;

    public ObservingService() {
        observables = new HashMap<String, Observable>();
    }

    public void addObserver(String notification, Observer observer) {
        Observable observable = observables.get(notification);
        if (observable==null) {
            observable = new Observable();
            observables.put(notification, observable);
        }
        observable.addObserver(observer);
    }

    public void removeObserver(String notification, Observer observer) {
        Observable observable = observables.get(notification);
        if (observable!=null) {         
            observable.deleteObserver(observer);
        }
    }       

    public void postNotification(String notification, Object object) {
        Observable observable = observables.get(notification);
        if (observable!=null) {
            observable.setChanged();
            observable.notifyObservers(object);
        }
    }
}
于 2012-04-26T04:46:51.720 回答
9

看看 Square 的 Otto 活动巴士:

http://square.github.com/otto/

它具有与 NSNotificationCenter 基本相同的功能,但由于注释和静态类型,它更容易遵循事件遵循的组件和路径的依赖关系。它比现有的 Android 广播 API IMO 更易于使用。

于 2012-12-20T10:00:20.180 回答
9

我有同样的奇迹..所以我写了这个:

public class NotificationCenter {

    //static reference for singleton
    private static NotificationCenter _instance;

    private HashMap<String, ArrayList<Runnable>> registredObjects;

    //default c'tor for singleton
    private NotificationCenter(){
        registredObjects = new HashMap<String, ArrayList<Runnable>>();
    }

    //returning the reference
    public static synchronized NotificationCenter defaultCenter(){
        if(_instance == null)
            _instance = new NotificationCenter();
        return _instance;
    }

    public synchronized void addFucntionForNotification(String notificationName, Runnable r){
        ArrayList<Runnable> list = registredObjects.get(notificationName);
        if(list == null) {
            list = new ArrayList<Runnable>();
            registredObjects.put(notificationName, list);
        }
        list.add(r);
    }

    public synchronized void removeFucntionForNotification(String notificationName, Runnable r){
        ArrayList<Runnable> list = registredObjects.get(notificationName);
        if(list != null) {
            list.remove(r);
        }
    }

    public synchronized void postNotification(String notificationName){
        ArrayList<Runnable> list = registredObjects.get(notificationName);
        if(list != null) {
            for(Runnable r: list)
                r.run();
        }
    }

}

一个用法是:

  NotificationCenter.defaultCenter().addFucntionForNotification("buttonClick", new Runnable() {
        @Override
        public void run() {
            Toast.makeText(MainActivity.this, "Hello There", Toast.LENGTH_LONG).show();
        }
    });

试图使界面尽可能类似于 IOS,但更简单(不需要对象注册)。

希望有帮助:)

于 2015-06-11T14:55:16.560 回答
2

在 Behlül 回答的基础上,我更改了代码以使其更接近 iOS NSNotificationCenter。

另一件事:通知将在主线程上触发

package com.oxygen.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.os.Handler;

public class NotificationCenter {

//---------------- event type list ---------------------

    public static enum NotificationID{
        IMAGES_CACHE_READY
    } 


//---------------- singelton ---------------------------    

        private static NotificationCenter instance = null;

        private NotificationCenter() { observables = new HashMap<NotificationID, MyObservable>();   }

        public static synchronized NotificationCenter singelton() {
            if (instance == null) {
                        instance = new NotificationCenter ();
            }
            return instance;
        }

//-------------------------------------------

                public class Notification {

                    private Object poster;  // the object that post the event
                    private Object info;    // event specific data 
                    private NotificationID id;      // event name

                    public Notification(Object poster, NotificationID id, Object info) {
                        super();
                        this.poster = poster;
                        this.info = info;
                        this.id = id;
                    }

                    public Object getPoster() {
                        return poster;
                    }

                    public Object getInfo() {
                        return info;
                    }

                    public NotificationID getId() {
                        return id;
                    }
                }
        //-------------------------------------------

                public interface Notifiable {
                    public void onNotification(Notification notify);
                }

//-------------------------------------------

        protected class MyObservable {
            List<Notifiable> observers = new ArrayList<Notifiable>();

            public MyObservable() {
            }

            public void addObserver(Notifiable observer) {
                if (observer == null) {
                    throw new NullPointerException("observer == null");
                }
                synchronized (this) {
                    if (!observers.contains(observer))
                        observers.add(observer);
                }
            }

            public int countObservers() {
                return observers.size();
            }

            public synchronized void deleteObserver(Notifiable observer) {
                observers.remove(observer);
            }

            public synchronized void deleteObservers() {
                observers.clear();
            }

            public void notifyObservers(Notification notify) {
                int size = 0;
                Notifiable[] arrays = null;
                synchronized (this) {
                        size = observers.size();
                        arrays = new Notifiable[size];
                        observers.toArray(arrays);
                }
                if (arrays != null) {
                    for (Notifiable observer : arrays) {
                        observer.onNotification(notify);
                    }
                }
            }
        }

//-------------------------------------------

        HashMap<NotificationID, MyObservable > observables;

        public void addObserver(NotificationID id, Notifiable observer) {
            MyObservable observable = observables.get(id);
            if (observable==null) {
                observable = new MyObservable ();
                observables.put(id, observable);
            }
            observable.addObserver(observer);
        }

        public void removeObserver(NotificationID id, Notifiable observer) {
            MyObservable observable = observables.get(id);
            if (observable!=null) {         
                observable.deleteObserver(observer);
            }
        }

        public void removeObserver(Notifiable observer) {
             for (MyObservable observable : observables.values()) {
                 if (observable!=null) {         
                    observable.deleteObserver(observer);
                }    
            }
        }

        public void postNotification(final Object notificationPoster, final NotificationID id, final Object notificationInfo) {

            final MyObservable  observable = observables.get(id);
            if (observable!=null) {

                // notification post to the maim (UI) thread    
                // Get a handler that can be used to post to the main thread
                Handler mainHandler = new Handler(AppContext.get().getMainLooper());

                Runnable myRunnable = new Runnable() {

                    @Override
                    public void run() {
                        observable.notifyObservers(new Notification(notificationPoster, id, notificationInfo) );
                    }
                };

                mainHandler.post(myRunnable);
            }
        }
}

监听器示例:

public class CustomGridViewAdapter extends ArrayAdapter<Category>  implements Notifiable {
    int layoutResourceId;

    public CustomGridViewAdapter(Context context, int layoutResourceId) {
        super(context, layoutResourceId);
        this.layoutResourceId = layoutResourceId;

        loadCategories(false);
        NotificationCenter.singelton().addObserver(NotificationID.IMAGES_CACHE_READY, this);
    }

    public void onDestroy() {
        NotificationCenter.singelton().removeObserver(this);            
    }

    @Override
    public void onNotification(Notification notify) {
        switch (notify.getId()) {
        case IMAGES_CACHE_READY:
            loadCategories(true);
            break;
        }
    }
...
}
于 2014-03-20T15:08:37.487 回答
2

如果您不想使用 Observer - 如果您希望 Fragment 成为您的 Observer,这可能会出现问题,因为您不能扩展一个以上的类 - 您可以使用 google 的 Guava 库(https://code.google。 com/p/guava-libraries/ ) 用于 "Function" 和 "Multimap" - 虽然您也可以使用 HashMap> 作为 subscibersCollection

并实现这样的事情:

    import java.util.Collection;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.base.Function;

public class EventService {

    ArrayListMultimap<String, Function<Object, Void>> subscibersCollection;

    private static EventService instance = null;

    private static final Object locker = new Object();

    private EventService() {
        subscibersCollection = ArrayListMultimap.create();
    }

    public static EventService getInstance() {
        if (instance == null) {
            synchronized (locker) {
                if (instance == null) {
                    instance = new EventService();
                }
            }
        }
        return instance;
    }

    /**
     * Subscribe to the notification, and provide the callback functions in case
     * notification is raised.
     * 
     * @param notification
     *            - notification name
     * @param func
     *            - function to apply when notification is raised
     */
    public void addSubscription(String notification, Function<Object, Void> func) {
        synchronized (subscibersCollection) {
            if (!subscibersCollection.containsEntry(notification, func)) {
                subscibersCollection.put(notification, func);
            }
        }
    }

    /**
     * Remove subscription from notification
     */
    public void removeSubscription(String notification,
            Function<Object, Void> func) {
        synchronized (subscibersCollection) {
            subscibersCollection.remove(notification, func);
        }
    }

    /**
     * raise notification for all its subscribers
     * 
     * @param notification
     *            - notification name
     * @param data
     *            - update data
     */
    public void publish(String notification, Object data) {
        Collection<Function<Object, Void>> observableList = subscibersCollection
                .get(notification);
        for (Function<Object, Void> func : observableList) {
            func.apply(data);
        }
    }
}
于 2013-06-06T08:38:18.523 回答