1

Whether I set the onClick method programatically or in the xml file, I don't know how I can pass an extra parameters through it. In the following code:

    for (int i = 0; i < 6; i++) {
        rollView[i].setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                changeKeepRoll(i);
            }
        });
    }

I'm setting an onClickListener for 6 different TextViews and I want to call the method changeKeepRollwhich takes an integer parameter as an input, however I get the error 'Variable 'i' is accessed from within inner class, needs to be declared final'. What does this mean and how can I rectify it?

Juan Cruz Soler
  • 8,172
  • 5
  • 41
  • 44
Thomas Doyle
  • 113
  • 13

3 Answers3

2
  for (int i = 0; i < 6; i++) {
        final int temp = i;
        rollView[i].setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            changeKeepRoll(temp);
        }
    });
  }
Kushan
  • 5,855
  • 3
  • 31
  • 45
  • 1
    Java has a rule that if you use an anonymous inner class to instantiate an object, any variable used inside that has to either be declared inside that block or if you want to use a variable from outside the block, the object has to be final or effectively final (java 8) – Kushan Feb 09 '17 at 20:17
1

Implement the OnClickListener class and overload the method with different sets of parameters

public class myClass implements View.OnClickListener {
int changeKeepRoll;
    @Override
    public void onClick(View v) {

    }

    public void onClick(int i) {

    }
}

make the changeKeepRoll variable outside the scope of your method or make it final.

SBC
  • 112
  • 7
1

You can pass parameters to OnClickListener by implementing the interface:

class MyOnClickListener implements OnClickListener {

    private int i;

    public MyOnClickListener(int i) {
        this.i = i;
    } 

    public void onClick(View view) {
        changeKeepRoll(i);
    }
}

And, your for loop will look like:

for(int i = 0; i < rollView.length; i ++) {
    rollView[i].setOnClickListener(new MyOnClickListener(i));
}

This has been asked before: How to pass parameters to OnClickListener?

Hope this helps, Bala

Community
  • 1
  • 1
BhalchandraSW
  • 714
  • 5
  • 13
  • @Thomas Doyle This answer is the best practise... My answer is a hack to fool the compiler, i just wanted to help you not change too much of your code ;) – Kushan Feb 09 '17 at 20:33
  • @Kushan I think you are underestimating yourself here - it's not a hack nor is it fooling the compiler. They way closures work (the anonymous thing has to close over the variable) with loop variables, this is a real fix. .Net has the same requirement - it's not about the implementation or compiler, it's with the philosophy 'metaphysics' of closure itself. (of course the compiler could automate this but YUCK). – FastAl Jul 08 '19 at 15:03