8

I am trying to use a loop to set the action for each button when clicked (since most of the buttons will just return their text value), however I am getting an error stating "variable 'i' is accessed from within inner class, needs to be declared final". How can I get around this?

Here is what I got

String getValuesPressed(){

    for(int i = 0; i < buttonList.length; i++){

        buttonList[i].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(i == 0){//error occurs here
                    //do stuff
                }

            }
        });
    }
    return textOnScreen;
}

3 Answers 3

13

You can copy the value of i in to a temp final variable as -

for (int i = 0; i < buttonList.length; i++) {
        final int finalI = i;
        buttonList[i].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (finalI == 0) {//error occurs here
                    //do stuff
                }
            }
        });
    }
Sign up to request clarification or add additional context in comments.

Comments

2

You are creating an anonymous class (View.OnClickListener) for each button, the onClick() method within that class has a different scope than the method getValuesPressed(), therefore it has no access to local variable i.

The solution is contained within the link provided above:

An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final.

Therefore introducing a final variable into the loop would resolve the error:

String getValuesPressed(){

    for(int i = 0; i < buttonList.length; i++){
        final int j = i;
        buttonList[i].setOnClickListener(new View.OnClickListener() {
            @Override 
            public void onClick(View v) {

                if(j == 0){//error occurs here
                    //do stuff 
                } 

            } 
        }); 
    } 
    return textOnScreen; 
} 

Comments

1

You could create you own listener that takes the position as a parameter to workaround the fact you are using an anonymous inner class.

private class MyClickListener implements View.OnClickListener {

    int position;

    public MyClickListener (int position) {
        this.position = position;
    } 

    @Override 
    public void onClick(View v) {
        if(position == 0){
            //do stuff 
        } 
    } 
} 

Then in your loop you can create it like this

String getValuesPressed(){

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

    return textOnScreen; 
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.