Using a loop to set the buttons onclicklistener

2019-06-19 21:30发布

问题:

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;
}

回答1:

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
                }
            }
        });
    }


回答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; 
} 


回答3:

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; 
}