2012-04-26 17 views
11

Czy istnieje odpowiednik klasy NSNotificationCenter dla systemu iOS w systemie Android? Czy są dostępne jakieś biblioteki lub użyteczny kod?Odpowiednik rozwiązania NSNotificationCenter dla systemu iOS w systemie Android?

+0

Czy masz na myśli NSNotificationCenter, lub cień powiadomienia? – CodaFi

+0

NSNotificationCenter, choć nie wiem, jaki jest cień powiadomienia :) Moją potrzebą jest nadawanie zdarzeń wielu obserwatorom za pomocą wzoru obserwatora. – user310291

+1

Wygląda na to, że [LocalBroadcastRajevers API] (http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html) jest tym, czego szukasz. – CodaFi

Odpowiedz

17

W systemie Android nie ma centralnego centrum powiadomień, tak jak w systemie ios. Ale można zasadniczo użyć obiektów Observable i Observer, aby osiągnąć swoje zadanie.

Można zdefiniować klasę jak coś poniżej, wystarczy zmodyfikować go do singleton wykorzystania i dodać zsynchronizowane do jednoczesnego stosowania, ale idea jest ta sama:

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); 
     } 
    } 
} 
+0

OK dziękuję za próbkę kodu :) – user310291

+0

Przed wywołaniem "notifyObservers()" potrzebujesz (lub przynajmniej w moim przypadku) wywołaj metodę "setChanged()". Stworzyłem więc mój niestandardowy obiekt Observable: http://pastebin.com/hqCuKRzW – jihonrado

+0

Edytowałem moją oryginalną odpowiedź @jihonrado, dzięki –

8

Spójrz na autobusie zdarzeń Otto od placu:

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

ma zasadniczo takie same cechy jak NSNotificationCenter ale dzięki adnotacje i typowania statycznego łatwiej jest śledzić zależności elementów i ścieżek, które wydarzenia następują. Jest znacznie prostsze w użyciu niż seryjny interfejs API Android, IMO.

2

Jeśli nie chcesz używać Observer - może to być problematyczne w przypadku chcesz Fragment być twój Obserwator przyczyna nie może trwać dłużej niż jeden wykładowa Można użyć Guava Biblioteka Google (https://code.google.com/p/guava-libraries/) dla „funkcja” i „Multimap” - choć można użyć również HashMap> dla subscibersCollection

i zaimplementować coś takiego:

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); 
     } 
    } 
} 
2

na podstawie Behlül odpowiedź, zmienić kod, aby jest bliżej centrum NSNotificationCenter iOS.

Kolejna rzecz: powiadomienia będą uruchamiane w głównym wątku

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); 
      } 
     } 
} 

Listener próbki:

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; 
     } 
    } 
... 
} 
6

miałem ten sam wondrings .. więc napisałem tak:

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(); 
     } 
    } 

} 

i użycie do tego będzie:

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

starał się, aby interfejs był jak najbardziej zbliżony do IOS, ale prostszy (bez rejestracji obiektu).

mam nadzieję, że pomaga :)

+1

Bardzo czyste rozwiązanie. – pstoppani

Powiązane problemy