public void method in for loop; can't recieve loop variable - java

Here's my for loop. Problem: I need to get a listener on an array of buttons and get the button depending on array number appending some text to a textview array with the same number.
Problem is, I can't get int i to the public void method. If I declare it my main class, the application just gets failed. When I'm changing the i value to some real integer, it works. so I figured out that the problem is - onClick method is receiving a null instead of i.
for(int i=0; i<n;i++){
btninput.get(i).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
converswindow.get(i).append(Html.fromHtml("<b>Вы:</b> "+msginput.get(i).getText()+"<br />"));
msginput.get(i).setText("");
}
});
}

I'm not sure if this would work or not, but try:
for(int i=0; i<n; i++) {
final int j = i;
btninput.get(i).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
converswindow.get(j).append(Html.fromHtml("<b>Вы:</b> "+msginput.get(i).getText()+"<br />"));
msginput.get(j).setText("");
}
});
}
If that doesn't work, you can use Android's View tag mechanism to add data to the button. Read about View.setTag(...) and View.getTag(...) for more information there.

anonymous classes can't access local vars in their methods you need to make them instance vars of the objects (here I did it with ind)
for(int i=0; i<n;i++){
btninput.get(i).setOnClickListener(new OnClickListener() {
int ind=i;//here keep a copy of the local var
#Override
public void onClick(View v) {
converswindow.get(ind).append(Html.fromHtml("<b>Вы:</b> "+msginput.get(ind).getText()+"<br />"));
msginput.get(ind).setText("");
}
});
}

try using
public void onClick(View v) {
converswindow.get(btninput.indexOf(v)).append(Html.fromHtml("<b>Вы:</b> "+msginput.get(btninput.indexOf(v).getText()+"<br />"));
msginput.get(btninput.indexOf(v)).setText("");

Or you could create a custom OnClickListener and give it a constructor that receives an int:
public class CustomListener implements OnClickListener {
int i;
CustomListener(int i) {
this.i = i;
}
#Override
public void onClick(View v) {
converswindow.get(j).append(Html.fromHtml("<b>Вы:</b>"+msginput.get(i).getText()+"<br />"));
msginput.get(j).setText("");
}
}
Then you could call it like this:
btninput.get(i).setOnClickListener(new CustomListener(i));

Related

Variable 'i' is accessed from within inner class, needs to be declared final

I'm trying to send value to another activity intent.putExtra("doctor",String.valueOf(items.get(i)));
but it gives error. That's "Variable 'i' is accessed from within inner class, needs to be declared final". The code is running in the for loop so I can't give final value because it's iterator.
How can we solve it?
Part of code
for (int i = 0; i < c; i++) {
items.add(options[i]);
spinnerDialog=new SpinnerDialog(NewActivity.this,items,"Search","Close");// With No Animation
spinnerDialog=new SpinnerDialog(NewActivity.this,items,"Search",R.style.DialogAnimations_SmileWindow,"Close");// With Animation
spinnerDialog.setCancellable(true); // for cancellable
spinnerDialog.setShowKeyboard(false);// for open keyboard by default
spinnerDialog.bindOnSpinerListener(new OnSpinerItemClick() {
#Override
public void onClick(String item, int position) {
Intent intent = new Intent(NewActivity.this,PrescriptionActivity.class);
intent.putExtra("doctor",String.valueOf(items.get(i)));
NewActivity.this.startActivity(intent);
}
});
findViewById(R.id.show).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
spinnerDialog.showSpinerDialog();
}
});
}
The variables used in the anonymous classes implementations (or lambda expressions) must be effectively final, or else the undefined behavior would happen.
I suppose that you want to handle on click action the item at the position obtained from the method using the int position, not from the outer loop. Do the following:
spinnerDialog.bindOnSpinerListener(new OnSpinerItemClick() {
#Override
public void onClick(String item, int position) {
Intent intent = new Intent(NewActivity.this,PrescriptionActivity.class);
intent.putExtra("doctor",String.valueOf(items.get(position))); // here
NewActivity.this.startActivity(intent);
}
});

I wanna perform back & forth functionality animation, I've used odd & even click counts but it stops after 1st cycle

//Initializing clickCount
int clickCount = 0;
public void animateButton(View view) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clickCount++;
if(clickCount%2==0 && clickCount==0){ //clickCount=0 declared in global variable
button.animate().translationX(400);
}
else {
button.animate().translationX(-400);
}
}
});
Or you can suggest any other method too.
Your if statement is true only once, at initialization. Afterwards clickCount is 1,2,3,... which is clickCount==0 : False so the if statement is also false.

access to variable within inner class in Android

i'm trying to generate a set of buttons whith data from the database. But on click i'm facing the following eror
Variable 'i' is accessed from within the inner class, needs to be declared final,
Since the value of i is changes as loop goes on i cannot set it as final,
footnoteBtns[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
footnote = myDbHelper.getFootnote(chapterNumber, translationList.get(i).get("transNo"));
Popup();
}
});
You could add an additional variable that is final and set to i:
final int j = i;
And then use that one inside the overridden onClick method.
The reason why you have to do this, is that onClick is called at another point of time and not directly inside the for loop -> asynchronous. Therefore, you need to make sure that it is clear which value should be used in that later called method. That's why the variable needs to be final.
In general it very weird approach to put setOnClickListener in a loop, but in your case you can solve it with following code:
for( int i = 0; i < N; i++) {
final int p = i;
footnoteBtns[p].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
footnote = myDbHelper.getFootnote(chapterNumber, translationList.get(p).get("transNo"));
popup();
}
});
}
Try this in place of current code:
class MyOnClickListener extends View.OnClickListener {
private int myi;
public MyOnClickListener(int i) {
myi = i;
}
#Override
public void onClick(View v) {
footnote = myDbHelper.getFootnote(chapterNumber, translationList.get(myi).get("transNo"));
Popup();
}
};
footnoteBtns[i].setOnClickListener(new MyOnClickListener(i));

Creating a Basic Undo Manager for Integer Values

I want to design a basic command pattern that will save integer values and be able to execute a undo method. I'm not sure where to start at all so any help would be much appreciated. Very basic interpretations like below:
package com.k.s;
public class MainActivity extends Activity {
public int Counter = 0;
#Override
protected void onCreate(Bundle savedInsanceState) {
super.onCreate(savedInsanceState);
setContentView(R.layout.activity_main);
Button.setOnClickListener (new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Counter += 1;
}
}
}
}
add action to the stack and remove it for "undo". example of command pattern: https://berther.io/2004/09/16/using-the-command-pattern-for-undo-functionality

scope of a variable

How can I get the value of a method parameter "myInteger" in this code.
public void myMethod(int myInteger) {
View.OnClickListener myClearHandler = new View.OnClickListener() {
public void onClick(View v) {
//***How can I get the value of "myInteger" here?***
}
};
}
Assuming you're just trying to read it, you just need to make it final:
public void myMethod(final int myInteger) {
View.OnClickListener myClearHandler = new View.OnClickListener() {
public void onClick(View v) {
int foo = myInteger;
}
};
}
In Java, only final parameters and local variables can be accessed within anonymous inner classes.
I am guessing the language should support closures and all you need to do in this case is use the variable myInteger in your onClick listener and you should be fine.. This works in fine in many languages I am not sure about Java though.
public void myMethod(final int myInteger) {
View.OnClickListener myClearHandler = new View.OnClickListener() {
public void onClick(View v) {
int myInteger = myInteger * 100;
}
};
}
AS posted by John Skeet: the final keyword is important here.
You Cannot refer to a non-final variable myInteger inside an inner class
defined in a different method
You might be getting this error, so for that you have to declare it as final like this
final int myInteger

Categories

Resources