Android: Listening for variable changes

user1977217 picture user1977217 · Jan 22, 2013 · Viewed 51.1k times · Source

I've been searching for a KISS example of how to do this, and while they all seem (and I've gone through them ALL!) simple enough, I still cannot get my head around the concept. I'm referring to custom listeners (ones that do not extend anything)... In particular, creating a listener for a boolean variable so that I can set off some methods when its value changes.

this is an example of an example I've tried: android how to make listener to a custom variable?

If someone has the time to explain a custom listener and how it works in plain English, that would be much appreciated. I'm hoping that once I understand exactly how the listener is notified of a change, then I'll be able to create my own and understand how the damn thing works. This is giving me a headache... Thanks in advance

Here is where I'm at at the moment:

public class ChangeListener {
    boolean boo = false;

    public ChangeListener(boolean b){
        boo = b;
    }

    private listener l = null;

    public interface listener{
        public void onChange(boolean b);
    }

    public void setChangeListener(listener mListener){
        l = mListener;
    }

    public void somethingChanged(){
        if(l != null){
            l.onChange(boo);
        }
    }


}

This is a snapshot of my main activity:

public class Main extends Activity implements ChangeListener.listener{
    private ChangeListener listener;
    private boolean boo = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        listener = new ChangeListener(boo);
        listener.setChangeListener(this);
        listener.somethingChanged();

    }

    @Override
    public void onChange(boolean b) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "REST = "+b, Toast.LENGTH_SHORT).show();
    }


}

Now, when the activity starts, the Toast displays the state of boo... great. Problem is this only happens within onCreate, which makes sense as .somethingChanged is placed in there. What I would like is for the Toast to be generated every time boo is changed from false to true, and true to false regardless if its within onCreate or not. I.e:

  • Click a button
  • Causes boo to change from false to true
  • Listener picks up on the change and runs whatever is in onChange

I know I could just use the button actionListener to do this, but I would like to stay away from this if possible, which at the moment I'm starting to think is impossible.

Any insight would be much appreciated. Thanks in advance!

Answer

Tatarize picture Tatarize · Aug 18, 2016

You wrap the variable up inside a custom class such that the only access functions also trip the listener. So that the only way to flip the switch is via the functions which toggles and calls the listener.

public class BooVariable {
    private boolean boo = false;
    private ChangeListener listener;

    public boolean isBoo() {
        return boo;
    }

    public void setBoo(boolean boo) {
        this.boo = boo;
        if (listener != null) listener.onChange();
    }

    public ChangeListener getListener() {
        return listener;
    }

    public void setListener(ChangeListener listener) {
        this.listener = listener;
    }

    public interface ChangeListener {
        void onChange();
    }
}

To monitor the change you need to implement BooVariable.ChangeListener and then pass the BooVariable class a copy of "this" then, when you change the variable it calls onChange.

Also, keeping in mind you can just inline the code rather than extend directly:

BooVariable bv = new BooVariable();
bv.setListener(new BooVariable.ChangeListener() {
    @Override
    public void onChange() {
        Toast.makeText(MainActivity.this,"blah", Toast.LENGTH_LONG).show();
     }
});

PS. The toast must be called from the UI thread, so you need to switch the Looper if you're going to change the variable in a different thread. This likely won't come up though.