Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically append functionality to Button's onclicklistener Android

Aim: I'm looking for a way to append functionality to a button's onClickListener.

Illustration

    Button trigger = new Button(getActivity());
    trigger.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            method1();
        }
    });

    Button runMethod2Button = new Button(getActivity());
    runMethod2Button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            method1();
            method2();
        }
    });

    Button runMethod3Button = new Button(getActivity());
    runMethod3Button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            method1();
            method3();
            method4();
        }
    });

I know we can do this with inheritance by calling

@Override
public void method(){
    super.method();
    // Do appended stuff
}

Or we can do it inline

new Object(){
    @Override
    public void method(){
        super();
        // Do appended stuff
    }
}

Things I've Tried

Extending the button to contain a list of Runnable Objects. Then set the on click listener to trigger all of the runnable objects.

Is there a different/more efficient way of doing this?

like image 625
SalicBlu3 Avatar asked May 29 '15 00:05

SalicBlu3


1 Answers

Since we don't no much about the background why you want to do so, it is hard to what is the best. If you want to have the original listener unchanged / untouched, you could use a decorator / wrapper pattern.

Wikipedia Decorator Pattern

In the concrete case this means, it is quite comparable to your Runnable approach, but you do not depend on another Interface. Everthing is handled via the View.OnClickListener, which has the following advantages:

  1. It is a generic approach with which you can even "extend" listeners to which you have no source access or which you do not want to modify.
  2. You can create the extension behaviour at runtime and you can extend already instantiated listeners (in contrast to the use of inheritance)
  3. The extensions do not have to know that they are extensions, they are just normal OnClickListeners. In your Runnable approach the extensions are "special" and for example they do not get the View paramter of the onClick method passed.

    public class OriginalOnClickListener implements View.OnClickListener{
    
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this,"Original Click Listener",Toast.LENGTH_LONG).show();
        }
    }
    
    public class ExtensionOnClickListener implements View.OnClickListener{
    
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this,"Extension Click Listener",Toast.LENGTH_LONG).show();
        }
    }
    
    public class DecoratorOnClickListener implements View.OnClickListener {
    
        private final List<View.OnClickListener> listeners = new ArrayList<>();
    
        public void add(View.OnClickListener  l) {
            listeners.add(l);
        }
    
        @Override
        public void onClick(View v) {
            for(View.OnClickListener l : listeners){
                l.onClick(v);
            }
        }
    }
    

And the usage is like this:

    DecoratorOnClickListener dl = new DecoratorOnClickListener();

    dl.add(new OriginalOnClickListener());
    dl.add(new ExtensionOnClickListener());

    editText.setOnClickListener(dl);
like image 159
Wildsau Avatar answered Sep 21 '22 15:09

Wildsau