2012-04-26 9 views
11

Esiste un equivalente della classe iOS NSNotificationCenter in Android? Sono disponibili librerie o codice utile?Equivalente di iOS NSNotificationCenter in Android?

+0

Intendi NSNotificationCenter o l'ombra di notifica? – CodaFi

+0

NSNotificationCenter anche se non so quale tonalità di notifica è :) La mia necessità è quella di trasmettere eventi a più osservatori tramite Observer Pattern. – user310291

+1

Sembra che [l'API LocalBroadcastRecievers] (http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html) sia ciò che stai cercando. – CodaFi

risposta

17

In Android non esiste un centro di notifica centrale come in ios. Ma puoi sostanzialmente utilizzare gli oggetti Observable e Observer per raggiungere il tuo compito.

È possibile definire una classe come qualcosa sotto, basta modificare per uso Singleton e aggiungere sincronizzati per l'uso concomitante, ma l'idea è la stessa:

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, grazie per il codice di esempio :) – user310291

+0

Prima di chiamare "notifyObservers()" è necessario (o almeno nel mio caso) chiamare il metodo "setChanged()". Così ho creato la mia custom Observable: http://pastebin.com/hqCuKRzW – jihonrado

+0

Ho modificato la mia risposta originale @jihonrado, grazie –

8

Date un'occhiata al bus evento Otto da Piazza:

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

essa ha essenzialmente le stesse caratteristiche NSNotificationCenter ma grazie ad annotazioni e tipizzazione statica è più facile seguire le dipendenze di componenti e percorsi che seguono eventi. È molto più semplice da usare rispetto all'API di trasmissione Android, IMO.

2

Se non si desidera utilizzare Observer - può essere problematico in casi che si desidera un frammento per essere il vostro Observer causa non è possibile estendere più di un classe- È possibile utilizzare Guava Biblioteca di Google (https://code.google.com/p/guava-libraries/) per "funzioni" e "Multimap" - anche se è possibile usare come bene HashMap> per la subscibersCollection

e realizzare qualcosa di simile:

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

Sulla base di Behlul risposta, modificare il codice per rendere è più vicino a iOS NSNotificationCenter.

Un'altra cosa: le notifiche fuoco sul thread principale

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 campione:

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

Ho avuto lo stesso wondrings .. quindi ho scritto questo:

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

} 

e un utilizzo per questo sarà:

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

ha cercato di rendere l'interfaccia più simile a IOS possibile, ma più semplice (non è necessaria la registrazione dell'oggetto).

speranza che aiuti :)

+1

Soluzione molto pulita. – pstoppani

Problemi correlati