Android: Java cannot refer to a non-final variable - java

In my Android application, when the users click on Sales button, it will show another view to perform the sales.
My application is working without having any problems before I have implemented an alert dialog to display a warning message to users if GST License expiry date of selected customer is less than 7 days and going to expire soon. Now I am getting the following error message if I don't declare final to these two variables, customer and v.
Cannot refer to a non-final variable customer inside an inner class defined in a different method
Cannot refer to a non-final variable v inside an inner class defined in a different method
I understand that
The reference declared as final cannot be modified once it is
initialized.
So, what will happen if I assign these two variables as final? It always contain the same value? Can someone please explain to me why the compiler giving me these errors and why I should declare final to these two variables?
Here is my source code:
private OnClickListener salesBtnClick = new OnClickListener() {
#Override
public void onClick(View v) {
Customer customer = salesCustAdpt.getSelectedCustomer();
if (customer != null) {
Date expiryDate = customer.getGSTLicenseExpiryDate();
if (checkCustomerGSTLicenseExpiryDate(expiryDate)) {
AlertDialog.Builder builder = new AlertDialog.Builder(SalesCustomerActivity.this);
builder.setCancelable(false)
.setPositiveButton(
"OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
try {
//Perform sales here!
Intent intent = null;
intent = new Intent(v.getContext(), SalesActivity.class);//Error msg here!
Bundle bundle = new Bundle();
bundle.putSerializable("selCustomer", customer);//Error msg here!
intent.putExtra("bundle", bundle);
startActivity(intent);
finish();
} catch (Exception ex) {
AddPlusUtil.displayErrorMsg(
SalesCustomerActivity.this,
ex);
}
}
});
AlertDialog alert = builder.create();
alert.setTitle("Warning Message");
String errMsg = "GST License Expiry Date of selected customer is \n" + expiryDate + " and going to expire soon.";
alert.setMessage(errMsg);
alert.setIcon(android.R.drawable.stat_notify_error);
alert.show();
} else {
//Perform Sales
}
}
}
}

When defining Customer, use final:
final Customer customer = salesCustAdpt.getSelectedCustomer();
Also, in your onClick method, set the View as final:
public void onClick(final View v) {
Hope this helps :)

Define that customer and v globally in your class. It will resolve the issue.
Create one global view object than assign it with your v
globalView = v;
and use that globalView for calling intent.
and by the way you can use yourClass.this as context instead of your view context.

Related

Assign value to variable using popup edit text on android studio

I'm trying to make a popup box with edit text field on Android Studio and would like to store the data entered by the user in a variable used in that class.
Something like this:
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("New player")
.setMessage("Input new player's name")
.setView(input)
.setPositiveButton("Register", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
name = input.getText().toString(); //<---HERE !want to use this variable
}
})
.setNegativeButton("Cancel", null)
.show();
This doesn't work, so how could I extract the value of name from my popup window to use it in the main code?
Do it this way:
final String[] name = new String[1];
final EditText input = new EditText(this);
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("New player")
.setMessage("Input new player's name")
.setView(input)
.setPositiveButton("Register", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
name[0] = input.getText().toString(); <---HERE! want to use this variable
}
})
.setNegativeButton("Cancel", null)
.show();
Access it using name[0]
Clarification for the followup question by Jox in the comment below: To access the variable inside onClick it needs to be final. But, you cannot assign a value to a simple final variable. However, you can assign a value to a Array member. Hence, the array and not a string variable. Btw, Andriod Studio will do it for you this way itself, just follow the suggested fixes for erroring-out code.
You should declare the DialogInterface.OnCLickListener inside of your Activity. By either creating a listener and assingning it or having your activity implement the interface. And then you won't need to declare name as final.
The reason you have to declare name as final is because you're anonmously creating an object to listen to the click, which require a contract of anything external being used by this anonymous class must be declared as final.
I would recommend creating a listener in your Activity and then assign it to the setOnClickListener(x)
Try this, it works for me :
public class Activity extends AppCompatActivity implements DialogInterface.OnClickListener {
private EditText input;
private String str = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
input = new EditText(this);
}
public void onClickAlert(View v) {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("New player")
.setMessage("Input new player's name")
.setView(input)
.setPositiveButton("Register", this)
.setNegativeButton("Cancel", null)
.show();
//variable str still equal to "" here
}
#Override
public void onClick(DialogInterface dialog, int which) {
str = input.getText().toString(); /*<---HERE! want to use this variable*/
//use it here
Log.d("Activity", "User input : " + str);
}
}
Implement the OnClickListener in your Activity and read the value of the text field in the callback fonction.

Get the click result in outer class AlertDialog

Good day to All! I'll try to describe my question. It's something in architecture scope...as I believe. So, let's start.
I have an activity where the user can create new player or click list and get the list of already created players. So in activity.java I create DatabaseHelper and SQLiteDatabase and use it for INSERT (if new player) or SELECT (if the player choose the existing one). To fill the list I use ListView and Adapter.
When user click (shortly) on the player name in the list, he get the AlertDialog with question "Do you want to proceed with player XXX?" If NO I simply cancel, if YES I take the name, create intent and start another activity with player name transferred intent.putExtra("name", LoginDialog.selectedName)) to that another activity. That's quite good. But now I want to allow user to delete player. The idea is - after a long click user get AlertDialog with question "Do you really want to delete player XXX?" NO - it's clear - cancel. But how to cope with YES?
Roughly - after YES I have to connect to DB and perform DELETE query. How I tried:
public class DeleteDialog {
AlertDialog.Builder ad;
public static Context context;
public static String selectedName;
public DatabaseHelper mDatabaseHelper;
public SQLiteDatabase mSqLiteDatabase;
public void dialogOfSelectedName(Context context, String selectedName) {
context = this.context;
selectedName = this.selectedName;
ad = new AlertDialog.Builder(context);
ad.setTitle("Удаление игрока");
ad.setMessage("Удалить игрока " + selectedName + "?");
ad.setCancelable(true);
mDatabaseHelper = new DatabaseHelper(context, "mydatabase.db", null, 1);
mDatabaseHelper.getReadableDatabase();
mSqLiteDatabase = mDatabaseHelper.getWritableDatabase();
ad.setNegativeButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
mSqLiteDatabase.execSQL("DELETE FROM" + DatabaseHelper.DATABASE_TABLE + " WHERE " + DatabaseHelper.NAME_COLUMN + " LIKE '" + selectedName + "'");
}
});
ad.setPositiveButton("NO", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alert = ad.create();
alert.show();
}
}
The problem is selectedName cannot be seen from overridden method onClick but I need it in the query. How to realize it? Or my approach is totally wrong? Please, help with advice.
Thanks!
Make the variable as final. You will be able to access it in the onClick method.
Change
public void dialogOfSelectedName(Context context, String selectedName)
to
public void dialogOfSelectedName(Context context, final String selectedName)

How to store phone number chosen from contacts into a string?

I am trying to store a phone number that is chosen from the contacts into a string or anything so that I can call it from the different class...
This is my code for contact button
#Override
protected void onCreate(Bundle savedInstanceState)
{
// initialize
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
//vi1 = (TextView) findViewById (R.id.textView1);
co1 = (Button) findViewById (R.id.button3);
co1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);
}
});
}
And this is for the onActivityResult to show it to the textview
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PICK_CONTACT:
final TextView vi1 = (TextView) findViewById(R.id.textView1);
Cursor cursor = null;
String phoneNumber = "";
List<String> allNumbers = new ArrayList<String>();
int phoneIdx = 0;
try {
Uri result = data.getData();
String id = result.getLastPathSegment();
cursor = getContentResolver().query(Phone.CONTENT_URI, null, Phone.CONTACT_ID + "=?", new String[] { id }, null);
phoneIdx = cursor.getColumnIndex(Phone.DATA);
if (cursor.moveToFirst()) {
while (cursor.isAfterLast() == false) {
phoneNumber = cursor.getString(phoneIdx);
allNumbers.add(phoneNumber);
cursor.moveToNext();}
} else {
//no results actions
}
} catch (Exception e) {
//error actions
} finally {
if (cursor != null) {
cursor.close();
}
final CharSequence[] items = allNumbers.toArray(new String[allNumbers.size()]);
AlertDialog.Builder builder = new AlertDialog.Builder(MenuActivity.this);
builder.setTitle("Choose a number");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
String selectedNumber = items[item].toString();
selectedNumber = selectedNumber.replace("-", "");
vi1.setText(selectedNumber);
}
});
AlertDialog alert = builder.create();
if(allNumbers.size() > 1) {
alert.show();
} else {
String selectedNumber = phoneNumber.toString();
selectedNumber = selectedNumber.replace("-", "");
vi1.setText(selectedNumber);
}
if (phoneNumber.length() == 0) {
//no numbers found actions
}
}
break;
}
} else {
//activity result error actions
}
}
I wanted to store the output on the textview into a string or any type of other forms so that I can call it on a different class. Please help me. Thank you!
There are couple of ways by which you can access variable in other classes or Activity.
Database
shared prefrences.
Object serialization.
A class which can hold common data can be named as Common Utilities it depends on you.
It depend upon your project needs.
A. Database
SQLite is an Open Source Database which is embedded into Android. SQLite supports standard relational database features like SQL syntax, transactions and prepared statements.
Tutorials -- http://www.vogella.com/articles/AndroidSQLite/article.html
B. Shared Preferences
Suppose you want to store username. So there will be now two thing a Key Username, Value Value.
How to store
// Create object of SharedPreferences.
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
//now get Editor
SharedPreferences.Editor editor = sharedPref.edit();
//put your value
editor.putString("userName", "stackoverlow");
//commits your edits
editor.commit();
Using putString(),putBoolean(),putInt(),putFloat(),putLong() you can save your desired dtatype.
How to fetch
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String userName = sharedPref.getString("userName", "Not Available");
http://developer.android.com/reference/android/content/SharedPreferences.html
C. Object Serialization
Object serlization is used if we want to save an object state to send it over network or you can use it for your purpose also.
Use java beans and store in it as one of his fields and use getters and setter for that
JavaBeans are Java classes that have properties. Think of
properties as private instance variables. Since they're private, the only way
they can be accessed from outside of their class is through methods in the class. The
methods that change a property's value are called setter methods, and the methods
that retrieve a property's value are called getter methods.
public class VariableStorage implements Serializable {
private String inString ;
public String getInString() {
return inString;
}
public void setInString(String inString) {
this.inString = inString;
}
}
Set the variable in you mail method by using
VariableStorage variableStorage = new VariableStorage();
variableStorage.setInString(inString);
Then use object Serialzation to serialize this object and in your other class deserialize this object.
In serialization an object can be represented as a sequence of bytes that includes the object's data as well as information about the object's type and the types of data stored in the object.
After a serialized object has been written into a file, it can be read from the file and deserialized that is, the type information and bytes that represent the object and its data can be used to recreate the object in memory.
If you want tutorial for this refer this link
http://javawithswaranga.blogspot.in/2011/08/serialization-in-java.html
Get variable in other classes
D. CommonUtilities
You can make a class by your self which can contain common data which you frequently need in your project.
Sample
public class CommonUtilities {
public static String className = "CommonUtilities";
}

get/use radio button value android

I FIGURED OUT WHAT I WAS DOING. I HAD THE VARIABLE NAME IN QUOTES WITH THE REST OF THE URL STRING.
How do you save the value of a Radio button into a variable and use that variable later.
I can see the variable Day_Item in my LogCat and the value is in there but when try using Day_Item later it does not show the valuable.
Below is a section of my code that shows the buttons.
String Day_Item = null;
public class SearchDB extends Activity {
private static final String TAG = "MyApp";
String start_log = "STARTED";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_layout);
final RadioButton radio_monday = (RadioButton) findViewById(R.id.monday);
radio_monday.setOnClickListener(radio_listener);
cityspinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,long arg3)
{
int id = parent.getId();
if (spinner2_count2 < spinner2_count1 ) {
spinner2_count2++; }
else
{
String city_spinner_log = "CITY SPINNER";
Log.d(TAG, city_spinner_log);
String item = cityspinner.getSelectedItem().toString();
String nameContentType = "name";
String cityURL = "GetRestaurant.php?day=Day_Item&city=" + item;
Log.d(TAG, cityURL);
String shop_data = DataCall.getJSON(cityURL,nameContentType);
Log.d(TAG, shop_data);
Bundle bundle = new Bundle();
bundle.putString("shopData", shop_data);
Intent myIntent = new Intent(SearchDB.this, ShowRestaurant.class);
myIntent.putExtras(bundle);
startActivityForResult(myIntent, 0);
}
}
}
//ONCLICKLISTENER that saves RADIO value into a variable.
public OnClickListener radio_listener = new OnClickListener() {
public void onClick(View v) {
// Perform action on clicks
RadioButton rb = (RadioButton) v;
Day_Item = (String) rb.getText();
Log.d(TAG,Day_Item);
Toast.makeText(SearchDB.this, Day_Item, Toast.LENGTH_SHORT).show();
}
};
}
You would need a bit more code to get a good solid answer. Such as how is Day_Item allocated? And is it's scope global? Are you calling it from another activity or the one it's allocated within? These are just guesses at this point:
1) Are you sure your onClickListener isn't firing multiple times? Thus setting Day_Item to an undesired text or nothing at all?
2) Rather a question/answer,
"but when try using Day_Item later it does not show the valuable"
I'm assuming this means that it is null? Well if it's being set properly, and then it is being null'd... it either is being explicitly null'd by you somewhere (such as (1)) or else the allocation and scope are the issue area I believe...

findviewbyid returns null in a dialog

I have a custom dialog and when I try to get the value of an EditText it returns null.
This line returns null
EditText et = (EditText)findViewById(R.id.username_edit);
Here is the code in its entirety.
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_TEXT_ENTRY:
LayoutInflater factory = LayoutInflater.from(this);
final View textEntryView = factory.inflate(R.layout.alert_dialog_text_entry, null);
return new AlertDialog.Builder(TicTacToe.this)
//.setIconAttribute(android.R.attr.alertDialogIcon)
.setTitle(getTitleText())
.setView(textEntryView)
.setPositiveButton("JOIN GAME", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
try
{
EditText et = (EditText)findViewById(R.id.username_edit);
playerName = et.getText().toString();
}
catch (Exception e)
{
}
}
})
.create();
}
return null;
}
In my case:
First I must call the
dialog.show(),
and only after it I was able to use
dialog.findviewById(R.id.myID).
If I missed to call the show(), than I got a null back with findViewByID.
Try this:
EditText et = (EditText)textEntryView.findViewById(R.id.username_edit);
You have to tell in which view to find the id. Otherwise it will try to find the id in the view from the xml layout inflated by setContentView (usually declared in onCreate)
I faced a similar problem. In my case, I had a dialog with custom layout and in this layout had a radioButton. In order to solve that, I used the follow code:
View dialogLayout = factory.inflate(R.layout.dialog_layout, null);
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setView(dialogLayout);
RadioButton radiobt = (RadioButton) dialogLayout.findViewById(R.id.radioBt);
I was having the same problem, which presented itself in the following code snippet:
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.addbank_dialog);
dialog.show();
Button btnSaveBank = (Button)dialog.findViewById(R.id.btnSaveBank);
final EditText etBankName = (EditText)dialog.findViewById(R.id.etBankName);
btnSaveBank.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try{
String bank = etBankName.getText().toString();
SharedCommonData.dbOps.saveBankInDB(bank);
}
catch(Exception e){
e.printStackTrace();
}
Toast.makeText(SharedCommonData.context, "Bank Saved", Toast.LENGTH_SHORT);
refreshBanks();
dialog.dismiss();
}
});
etBankName was returning null value, but then I used dialog.findviewbyid(R.id.etBankName) and it worked.
In my case I had this error because I was redeclaring an initialized variable
In main Activity I had:
EditText cityName;
And in onCreate:
EditText cityName = (EditText)findViewById(R.id.cityName);
Just removed EditText and smooth sailing!
None of the existing answers worked for me, so I started trying different lifecycle hooks, and the one that worked for me was onViewCreated, which seems like a good choice semantically as well.
In my case what I did was that I was passing an ID of a view which was in different fragment and in that case the compiler gave me same error.
So try checking that the ID use pass is in the same xml which is connect to the java file.
I hope it helps this is my first ever solution given in this community.

Categories