access to variable within inner class in Android - java

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

Related

Is there any possible way to retrieve an ArrayList value from an OnCllickListener method and save it in it's parent method?

saveBtnYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveBtnYesFunc(currentYesBtnId);
tempActivityList =activityNames;
return activityNames;
}
});
When I call the saveBtnYesFunc function, it returns an ArrayList value called activityNames to the onClick thread. I want to pass that value from inside of the onClickListener method to its parent method (this code is contained within another method). The last line of code return activityNames won't work.
Is there any other way to do it?
You need to determine who is actually interested in seeing this new list. Assuming that the interested part is an instance of some class ListUsingClass, this should work.
final ListUsingClass listUser = new ListUsingClass(); // or assign to existing reference
saveBtnYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listUser.setActivityNames(saveBtnYesFunc(currentYesBtnId));
}
});
Your question isn't really clear, I think you want that when a Button is clicked, an Array (activityNames) is saved somewhere.
You can do this in this way, if I understood well:
class YourClass { //almost surely it extends Activity (or AppCompatActivity)
private List<String> thePlaceWhereTheArrayWillBeLocated = new ArrayList<String>(); //You should define a class varibale where the result of saveBtnYesFunc will ends up (I think that the content is of String type)
... onCreate(...) {
super.onCreate(savedInstanceState);
...
...
saveBtnYes.setOnClickListener(new View.OnClickListener() { //I don't know if it's inside the onCreate, but it could be here
#Override
public void onClick(View v) {
thePlaceWhereTheArrayWillBeLocated = saveBtnYesFunc(currentYesBtnId); //Maybe some type casts are needed
//tempActivityList =activityNames;
//return activityNames; //This line is totally incorrect
}
});
}
void wheneverFunctionYouWant() {
//do whatever you want with thePlaceWhereTheArrayWillBeLocated
}
}

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

using variable in another class

Iam creating an android app that has many classes inside the main Java package. The MainActivity class implements Button onClick Listener and do some coding with assigning values to variable x inside the method when button is clicked, now I have class#2 use the same variable x in some other coding. I want the onClick method when it is called to send the variable x value to class#2
MainActivityCalss {
hi.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int x = 1;
}
});
}
Class2 {
Method() {
y = x + 1;
}
}
Creating a new Java class to hold all global variables is a very good idea.
public class GlovalVariable{
public String x;
public int y;
// Generate getter/setter methods for all the variables defined here.
}
By creating this you will manage a variables very easily. If you want to rename the variable which is used through out the class, this method will make it very easy.
Define "x" in other class and set it using setter method, and where ever you get it through getter.
public class value {
public static int x;
public static void set(int value) {
x = value;
}
public static int get() {
return x;
}
}
And in onclicklistener of mainactivity.
hi.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
value.set(1);
}
});
In class2
Method() {
y = value.get()+1;
}

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

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

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

Categories

Resources