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;
}
Related
I'm having an inner class within another inner class, in which I'm trying to use final variable outside both inner classes. Here's the code:
final View v = inflater.inflate(R.layout.fragment_floor_plan, container, false); //final variable
final Button button0 = v.findViewById(R.id.button21);
button0.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final PhotoView photoView = v.findViewById(R.id.photo_view); //works fine here
photoView.setAlpha(0f);
System.out.println(photoView.isZoomable());
System.out.println(photoView.VISIBLE);
photoView1.animate().alpha(0f).setDuration(250);
photoView.animate().alpha(1f).setDuration(250);
photoView.bringToFront();
photoView.setOnScaleChangeListener(new OnScaleChangedListener() {
#Override
public void onScaleChange(float scaleFactor, float focusX, float focusY) {
if (photoView.getScale() <= photoView.getMinimumScale() + 0.1f) {
LinearLayout linearLayout = v.findViewById(R.id.linearLayout); //doesn't work here
linearLayout.bringToFront();
}
}
}
}
});
How to get it to work inside OnScaleChangedListener?
Now that I look at it, your problem might be that the View v is being passed as a parameter to the onClick method of the OnClickListener, and the code below might be trying to access instead of your top-level View variable.
My recommendation would be to refactor your variable names so that you are referring to the correct variable. If the passed-in View is the one you actually want to use, it should be declared as final in the method signature:
public void onClick(final View v) {
If the variable in the enclosing scope of the nested anonymous class is declared final or effectively final, you should just be able to access it from within any level of nested inner anonymous classes.
To ensure this I made a little example and tried it out myself:
import java.util.function.*;
public class Main {
public static void main(String[] args) {
final int test = 11;
Runnable runnable = new Runnable() {
public void run() {
Runnable runnable = new Runnable() {
public void run() {
System.out.println(test);
}
};
runnable.run();
}
};
runnable.run();
}
}
As you can see the second runnable is nested within another runnable, and running the code accesses the integer test and prints it as it should.
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'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));
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
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));