I want to reference a non-finite variable inside an inner class defined by another method

I am writing an Android application in which I have several buttons placed in a grid. I want to set the onClick method for each button, so I wrote the following:

for (int i = 0; i < button.length; i++) { for (int j = 0; j < button[0].length; j++) { button[i][j].setOnClickListener(new View.OnClickListener() { public void onClick(View v) { press(i, j); } }); } } 

where press(int i, int j) implemented elsewhere. I get an error: "You cannot reference a non-finite variable I inside an inner class defined by another method."

So, right now I have every function written out like this:

 button[0][0].setOnClickListener(new View.OnClickListener() { public void onClick(View v) { press(0, 0); } }); button[0][1].setOnClickListener(new View.OnClickListener() { public void onClick(View v) { press(0, 1); } }); // more like this... 

It works, but it seems stupid. Is there a better way?

+4
source share
6 answers

Yes, try the following:

 for (int i = 0; i < button.length; i++) { for (int j = 0; j < button[0].length; j++) { final int listenerI = i; final int listenerJ = j; button[i][j].setOnClickListener(new View.OnClickListener() { public void onClick(View v) { press(listenerI, listenerJ); } }); } } 
+6
source

You can define a helper method to set the listener for the button:

 private static void setListenerForButton(Button button, final int i, final int j) { button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { press(i, j); } }); } 

and then you can use it as follows

 for (int i = 0; i < button.length; i++) { for (int j = 0; j < button[0].length; j++) { setListenerForButton(button[i][j], i, j); } } 

This is a special case of a more general solution: define additional final int variables for use in the inner class and initialize them with the values i and j . In this case, the additional variables final int are the arguments to the helper function.

+4
source
 for (int i = 0; i < button.length; i++) { for (int j = 0; j < button[0].length; j++) { final int localI = i; final int localJ = j; button[localI][localJ].setOnClickListener(...); } } 
+2
source

Declare i and j as a global variable in the outer class

+1
source

you can go with one listener:

 package tayek.so9551773; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*; import android.util.Log; public class So9551773 extends Activity { void press(int i,int j) { Log.d("so",i+","+j+" was clicked"); System.out.println(i+","+j+" was clicked"); } void addButtons(TableLayout tableLayout) { for(int i=0;i<buttons.length;i++) { TableRow tableRow=new TableRow(this); tableLayout.addView(tableRow); for(int j=0;j<buttons[i].length;j++) { buttons[i][j]=new Button(this); tableRow.addView(buttons[i][j]); buttons[i][j].setText(i+" "+j); buttons[i][j].setId(i*buttons.length+j); buttons[i][j].setOnClickListener(onClickListener); } } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("so","created"); TableLayout tableLayout=new TableLayout(this); addButtons(tableLayout); setContentView(tableLayout); } Button[][] buttons=new Button[3][3]; OnClickListener onClickListener=new OnClickListener(){ public void onClick(View v) { int id=v.getId(); press(id/buttons.length,id%buttons.length); } }; } 
+1
source

Source: https://habr.com/ru/post/1399603/


All Articles