Search code examples
javaandroidobserver-patternobservableobservers

Observable/Observer not working?


I tried implementing a static Observable in my Application subclass, but it's not working. No exceptions or error messages, but my update() callback doesn't get called.

MyApplication.java

public class MyApplication extends Application{
    public static Observable appObserver = new Observable();

    public void onCreate(){
        super.onCreate();        
    }

}

Foo.java

MyApplication.appObserver.notifyObservers( "Hello world" );

BarFragment.java

public class BarFragment extends Fragment implements Observer{

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);                
        MyApplication.appObserver.addObserver(this);
    }


    @Override
    public void onDestroy() {       
        MyApplication.appObserver.deleteObserver(this);
        super.onDestroy();
    }


    @Override
    public void update(Observable observable, Object data) {
        Log.i("BarFragment", data.toString()); // Should log, but doesn't
    }

}

What's more, I tried scribbling down a simple Observable of my own, and then everything worked like a charm with just substituting public static Observable appObserver = new Observable(); with public static MyObservable appObserver = new MyObservable();

MyObservable.java

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

    public void addObserver(Object observer){
        observers.add(observer);
    }

    public void notifyObservers(Object data){
        for( int i=0; i<observers.size(); i++ ){
            ((Observer) observers.get(i)).update(null, data);
        }
    }
}

What am I missing?

I'm testing this on a Nexus One with Android 2.3.6 if it matters.


Solution

  • Seems I missed a crucial part of the Observer mechanism, apparently one has to call setChanged() before notifyObservers(). But the thing is, setChanged() is protected and thus only visible to any subclass of Observable.

    So I guess it's not meant to be used in the fashion I tried to use it, but the hackish subclass below will work...

    public class MyObservable extends Observable{
    
        @Override
        public boolean hasChanged() {
            return true; //super.hasChanged();
        }
    
    }