Android/Java understanding when I'm able to use/overwrite variable - java

I have a variable that I get from shared preferences when I load the app.
I first initialize the variable
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String camera_type = booth_preferences.getString("camera_key", "back");
Then later down the line, I get that variable and do something with it
if(camera_type.equals("front")){
//do something
} else if(camera_type.equals("ext")){
//do something
} else {
//do something
}
Now, directly after that if statement, I have an onclick listener that is supposed to change and update that preference.
camera_button_front.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//do something
edit_preferences.putString(camera_key, "front").commit();
}
});
camera_button_back.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//do something
edit_preferences.putString(camera_key, "back").commit();
}
});
camera_button_ext.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//do something
edit_preferences.putString(camera_key, "ext").commit();
}
});
But when I try to change the variable camera_type I get errors stating "cannot assign a value to final variable 'camera_type'".
camera_button_ext.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//do something
edit_preferences.putString(camera_key, "ext").commit();
camera_type = "ext";
}
});
I've ever reinstated the variable after the onclick hoping it would over write the variable completely.
camera_button_ext.setOnClickListener(new View.OnClickListener() {
String camera_type;
public void onClick(View v) {
//do something
edit_preferences.putString(camera_key, "ext").commit();
camera_type = "ext";
}
});
If I were to remove the final then I'm not able to use the variable in the if statement.
I'm new to Java, so this should be a simple answer, I'm just not sure which combination of wrong I'm doing.

You should make your variable a non-final field. Then you can use it within the onClick (and all other methods of the class) and also reassign it as you wish.
private String camera_type; // member variable
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
camera_type = booth_preferences.getString("camera_key", "back");

You cannot reassign value to a final variable. To make it accessible inside your onClick method, you could make camera_type a member variable of your activity.

You can make one element massive
String[] cameraType = new String[0];
and use
if("some_String".equals(cameraType[0])){
//do smth
}

Related

Setting Listeners programmatically to an array of CheckBoxes

So far, I've encountered the issue "variable x is accessed within inner class,needs to be declared final. I am able to initialize the CheckBox's but I am unable to set a listener to them after initialization in the loop. Below is my code so far.
for(int i=0;i<checkBox_fiber_ID.length;i++){
int temp=getResources().getIdentifier(checkBox_fiber_ID[i],"id",getPackageName());
checkBoxes_fiber[i]=findViewById(temp);
checkBoxes_fiber[i].setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
if(checkBoxes_fiber[i].isChecked()){
//do something
}
}
});
}
Any tips on how to solve this?
Take final String[] x={"defaultvalue Emptry"}
Then after inside onclick Listener set value of x using below code.
x[0]="new value"
and use this value in different function.
as per your code it look likes blow:
final String x[] ={""}
for(int i=0;i<checkBox_fiber_ID.length;i++){
int temp=getResources().getIdentifier(checkBox_fiber_ID[i],"id",getPackageName());
checkBoxes_fiber[i]=findViewById(temp);
checkBoxes_fiber[i].setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
if(checkBoxes_fiber[i].isChecked()){
x[0]=checkBoxes_fiber[i].getvalue==> value name
}
}
});
}
Outside function get value of x using
String name=x[0]
You can try to create separate class of listener
private View.OnClickListener mCheckboxListener = new View.OnClickListener() {
public void onClick(View v) {
if(((CheckBox)view).isChecked())
{
int checkBoxId = (int)v.getTag(); //You can get Id for specific checkbox
//do other stuff with checkBoxId
}
}
};
And set Id to each checkbox like
for(int i=0;i<checkBox_fiber_ID.length;i++){
int temp=getResources().getIdentifier(checkBox_fiber_ID[i],"id",getPackageName());
checkBoxes_fiber[i]=findViewById(temp);
checkBoxes.setTag(i); //set check box id as tag for later usage
checkBoxes_fiber[i].setOnClickListener(mCheckboxListener);
}
I guess you are trying to do something base on the checkbox IDs. You can set a tag for a checkBox and get back the tag in future. Also, the view object in method void onClick(View view) is now an CheckBox. Just change a little in your code:
for(int i=0;i<checkBox_fiber_ID.length;i++){
int temp=getResources().getIdentifier(checkBox_fiber_ID[i],"id",getPackageName());
checkBoxes_fiber[i]=findViewById(temp);
checkBoxes_fiber[i].setTag(i); //mark the check box id for later usage
checkBoxes_fiber[i].setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
if(((CheckBox)view).isChecked()){
int checkBoxId = (int)view.getTag();
doSomething(checkBoxId);
}
}
});
}
}
And write a new method for business code:
public void doSomething(int no){
if(no==1){
//do something
}
else if(no==2){
//do something
}
//...
}

How to declare boolean inside button click?

I want to set something like this on button click:
boolean isLightOn = false;
if(!isLightOn)
{
FlashTask.flash.on();
isLightOn=true;
return;
} else {
FlashTask.flash.off();
isLightOn=false;
return;
}
But it's not working...
Thanks advance.
Hard to know without seeing all your code. But you could declare a variable as field member, then change it on every button click.
That's the simpliest way:
public class MyActivity extends Activity {
//boolean field member initialized as false by default
private boolean isLightOn;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_layout_id);
final Button button = findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(isLightOn){
FlashTask.flash.off();
} else{
FlashTask.flash.on();
}
isLightOn = !isLightOn;
}
});
}
}
Every time the button is clicked, boolean isLightOn = false; is called and isLightOn will always be false when the button is clicked. You are not preserving the previous state.
To preserve the state, make isLightOn as a class variable and remove boolean isLightOn = false; from your listener method.
You need somthing like this.
private boolean isLightOn = false; //defined as class variable;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!isLightOn){
FlashTask.flash.on();
isLightOn=true;
}else {
FlashTask.flash.off();
isLightOn=false;
}
}
});
But make sure isLightOn is defined outside the listener scope.

How to access own variable upon initialization within inner class?

I have a "DialogHelper" class wherein a bunch of static methods are used in various contexts to make using Dialogs easier. One such method is a "three choice dialog" where the user has three buttons to choose from to go forward:
public static AlertDialog createThreeChoiceDialog(final MyActivity activity, String title, String firstChoiceText,
String secondChoiceText, String thirdChoiceText, View.OnClickListener firstChoiceListener, View.OnClickListener secondChoiceListener,
View.OnClickListener thirdChoiceListener) {
final View dView = activity.getLayoutInflater().inflate(R.layout.three_choice_dialog, null);
final TextView explanatoryTV = (TextView) dView.findViewById(R.id.explanatoryTV);
final TextView firstChoiceTV = (TextView) dView.findViewById(R.id.firstChoiceTV);
final TextView secondChoiceTV = (TextView) dView.findViewById(R.id.secondChoiceTV);
final TextView thirdChoiceTV = (TextView) dView.findViewById(R.id.thirdChoiceTV);
explanatoryTV.setText(title);
firstChoiceTV.setText(firstChoiceText);
secondChoiceTV.setText(secondChoiceText);
thirdChoiceTV.setText(thirdChoiceText);
firstChoiceTV.setOnClickListener(firstChoiceListener);
secondChoiceTV.setOnClickListener(secondChoiceListener);
thirdChoiceTV.setOnClickListener(thirdChoiceListener);
AlertDialog = etc...
return alertDialog;
}
And I call it like this:
private void doSomething() {
final AlertDialog alert = DialogHelper.createThreeChoiceDialog(activity, "title", "choice1", "choice2", "choice3",
new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something 1
alert.dismiss();
}
}, new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something 2
alert.dismiss();
}
}, new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something 3
alert.dismiss();
}
});
alert.show();
}
However, the "alert.show()" method rings up the error:
variable 'alert' might not have been initialized yet
My question is, what is the best way to handle this situation? I want to dismiss the dialog when the user selects a choice.
This is my current workaround:
private void doSomething() {
final ArrayList<AlertDialog> alerts = new ArrayList<>(); //<-- added ArrayList of AlertDialogs
final AlertDialog alert = DialogHelper.createThreeChoiceDialog(activity, "title", "choice1", "choice2", "choice3",
new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something 1
alerts.get(0).dismiss(); //<-- accessed via ArrayList
}
}, new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something 2
alerts.get(0).dismiss(); //<-- accessed via ArrayList
}
}, new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something 3
alerts.get(0).dismiss(); //<-- accessed via ArrayList
}
});
alerts.add(alert); //<-- add alert to ArrayList
alert.show();
}
It works, but there's no way that this can be a best practice. I've run into this problem a few times, so I finally decided to ask what the best way to handle it is.
You are basically trying to reference an instance of a class while declaring and creating that instance - this is not possible.
I see your options as the following:
1. Wrap AlertDialog
This is basically your work-around which uses an ArrayList, but you can create you own class for this purpose also.
2. Make AlertDialog a member
Declare alert be a private member of the class which contains the doSomething method, instead of declaring it in the method itself.
3. Replace your DialogHelper with a Builder
There are several advantages (and 1 disadvantage) to this approach.
The first advantage is that it will solve your problem. The second is because it's good coding practice: in general, having methods with take many parameters is considered dirty. In the case of them being constructor methods, Clean Code conventions recommend replacing them with builders.
The disadvantage of the implementation I am about to suggest is that the Dialog behaviour is that clicking an option will always dismiss the dialog.
public class MyDialogBuilder {
private AlertDialog alert;
public MyDialogBuilder withActivity(Activity activity){
final View dView = activity.getLayoutInflater().inflate(R.layout.three_choice_dialog, null);
alert = ...;
return this;
}
public MyDialogBuilder withFirstChoice(String choiceText, final ChoiceAction action){
final TextView firstChoiceTV = (TextView) alert.findViewById(R.id.firstChoiceTV);
firstChoiceTV.setText(choiceText);
firstChoiceTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
action.perform();
alert.dismiss();
}
});
return this;
}
// Similar implementations for the other methods here...
public AlertDialog create() {
return alert;
}
interface ChoiceAction {
void perform();
}
}
Your calling code would be like
MyDialogBuilder builder = new MyDialogBuilder();
AlertDialog alert = builder.withActivity(activity)
.withTitle("Dialog title")
.withFirstChoice("choice 1", new MyDialogBuilder.ChoiceAction() {
#Override
public void perform() {
//do something 1
}
})
.withSecondChoice("choice 2", new MyDialogBuilder.ChoiceAction() {
#Override
public void perform() {
//do something 2
}
})
.withThirdChoice("choice 3", new MyDialogBuilder.ChoiceAction() {
#Override
public void perform() {
//do something 3
}
})
.create();
I would recommend the third approach, as I think in most cases you want to close the Dialog when the user selects an option. If you want to show some progress bar in the dialog, you can create additional methods on MyDialogBuilder which would call alert.dismiss() in a callback. Hope this helps.

ANDROID JAVA - Define all id's at once. (+create easy buttons)

I am new to programming in Java, i've managed to create a little calculator as a little test app.
But i think i am using way to much code for my needs.
So i've given a Button a name: buttonname
Now to change it's text when clicked i need to:
public class MyActivity extends Activity {
Button buttonname;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
buttomname = (Buttom) findViewById(R.id.buttomname);
}
public void buttonnameOnClick(View v) {
button1.setText ("NewText")
}
}
(i've bolted everything i had to add)
So i had to do everything above + connect the buttonClick through the xml file.
So i was wondering if there is a easier way to define all objects so i dont have to do: Button buttonname; and buttomname = (Buttom) findViewById(R.id.buttomname); all the time.
And i was wondering if there is a easier way to auto create button events.
(I am used to Visual Studio, but now i am kinda lost in Android Studio. So on Visual Studio i just had to double click the button and type: buttonname.Text = "NewText";)
There is a library called Butter Knife to do approximately that
However, I'm not sure if you really need it.
Oh, and you don't have to find the same Button every time. You find it once in onCreate and store in a field.
First of all you have typo in
buttomname = (Buttom) findViewById(R.id.buttomname);
It should be
buttomname = (Button) findViewById(R.id.buttomname);
and you forgot ; in one line "didn't your IDE show error to you!!" and also small correction in
public void buttonnameOnClick(View v) {
button1.setText ("NewText")
}
it should be
buttomname.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
buttomname.setText ("NewText");
}
});
inside protected void onCreate.
2nd method:
And if you have define android:onclick="buttonnameOnClick" in XML then
public void buttonnameOnClick(View v) {
button1.setText ("NewText")
}
To be corrected to
public void buttonnameOnClick(View v) {
buttomname.setText ("NewText");
}
You can do it in a loop if you have a lot of identical buttons to process
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
for (int btn_id : new int[]{
R.id.buttomname
, R.id.buttomname2
, R.id.buttomname3
}) {
View v = view.findViewById(btn_id);
if (v != null) {
v.setOnClickListener(onClickButton);
}
}
}
//
private View.OnClickListener onClickButton = new View.OnClickListener() {
#Override
public void onClick(View view) {
// .. handle click
if (view.getId()==R.id.buttomname2){
}
}
Your code is partly correct,
however the
(Buttom) is wrong change it to (Button)
the other thing
public void buttonnameOnClick(View v) {
button1.setText ("NewText")
}
can just be changed to:
public void buttonnameOnClick(View v) {
Button buttonTemp = (Button)v;
buttonTemp.setText ("NewText");
}
Assuming you are calling the method from layout xml file.
you must use the onClickListener() method for Button object.
Your code like this structure;
buttonname = (Button)findViewById(R.id.buttonname);
buttonname.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
I recommend to your visit Button | Android Dev page for Button.

Method definition passed as argument

I saw this code when looking at an Android example:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editNumber;
Button btnCall = (Button) this.findViewById( R.id.btnCall);
editNumber = (EditText) this.findViewById(R.id.editNumber);
btnCall.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
call();
}
});
// ...
}
Here:
new OnClickListener() {
public void onClick(View v) {
call();
}
}
is passed to setOnClickListener() as a parameter. What I don't understand is what code inside {...} does here? if new OnClickListener() calls the constructor, and the constructor returns an object, yes, object can be passed to method as a parameter, but what is:
{
public void onClick(View v) {
call();
}
}
doing here? It looks like a method definition?
Thanks a lot for the help!
As #Perception said, it is an anonymous inner class. btnCall.setOnClickListenter() is expecting an argument that has the type OnClickListener. You could instantiate a concrete reference to an OnClickListener and pass that as an argument but if you are never going to refer to it again, sometimes it is easier to simply make an anonymous inner class.

Categories