This question already has answers here:
Misbehavior when trying to store a string set using SharedPreferences
(6 answers)
Closed 1 year ago.
When I try to save the first string in a stringSet to the sharedPreferences it saves normally, but after trying to save another string in stringSet it shows as if it was saved but when restarting the application and retrieving the data, it only shows the first string that was saved, when I try again clicking on the same functionality button, it won't save to sharedPreferecnes, but clicking another button that have the same functionality will save the previous which I found strange. here is my code
button.setOnClickListener {
val orderPrefs = getSharedPreferences("order", Context.MODE_PRIVATE)
val editor = orderPrefs.edit()
var test = orderPrefs.getStringSet("recentlyViewedRestaurant", null)
if (test == null) {
test = HashSet<String>(0)
}
test.add(restaurantName)
//Log.d("LastPicked", test.toString())
editor.putStringSet("recentlyViewedRestaurant", test)
editor.apply()
val testing = getSharedPreferences("order", Context.MODE_PRIVATE)
//it will retrieve and show the expected result but leaving the page
//and retrieving from another activity won't show the last added string
Log.d(
"lastPicked",
testing.getStringSet("recentlyViewedRestaurant", null).toString()
)
}
I don't see you adding ".apply()" after saving the string.
Ex:
val orderPrefs = getSharedPreferences("order", Context.MODE_PRIVATE)
val editor = orderPrefs.edit()
editor.putStringSet("recentlyViewedRestaurant", test).apply()
Related
So I want to add user in map and then check if it's added in there.
for instance, user enters their information, im saving their email as key and information in dataclass as value
private val users = mutableMapOf<String, User>()
private fun add(){
check()
val email = binding.email.text.toString()
val firstName = binding.firstname.text.toString()
val lastName = binding.lastname.text.toString()
val age = binding.age.text.toString()
users["default"] = User("email","firstName","lastName","age")
for (user in users.keys){
if (email == user) {
Toast.makeText(this,"not successful",Toast.LENGTH_SHORT).show()
break
}else{
users[email] = User(email,firstName,lastName,age)
Toast.makeText(this,"successful",Toast.LENGTH_SHORT).show()
}
}
}
but when i click on the button in first run, it just says successful, but on the second click it should return not successful because this user was already created, but it shows both toasts.
can u tell me why it does this and how can i fix it?
this has to do with the fact that the for loop has no guarantee that it will iterate the keys in the order you expect.
For example, consider this map:
users["default"] = User("email","firstName","lastName","age")
users["zzz#xyz.com"] = User("email","zz","z","age")
suppose that the keys would be iterated in alphabetical order(this is not actually the case most of the time) and that you had email=zzz#xyz.com
On the first iteration, the user string would refer to default. Since email == user is false, it would go to the else branch of your loop. Then, on the next iteration, user will be zzz#xyz.com and email == user will be true; just sending the "toast" notification twice.
It seems that you're trying to insert an element if it doesn't exists, or show an error if it does. Instead of a for loop, consider checking for the existence of the previous key with containsKey and then adding a new element if necessary.
// In kotlin, you can create a map with initial values by using the "to" infix function
private val users = mutableMapOf<String, User>(
"default" to User("email","firstName","lastName","age")
)
private fun add() {
check()
val email = binding.email.text.toString()
val firstName = binding.firstname.text.toString()
val lastName = binding.lastname.text.toString()
val age = binding.age.text.toString()
if (users.containsKey(email)) {
Toast.makeText(this,"not successful",Toast.LENGTH_SHORT).show()
return
}
users[email] = User(email,firstName,lastName,age)
Toast.makeText(this,"successful",Toast.LENGTH_SHORT).show()
}
This is because you are comparing the map key with the email value. You need to compare the value of the email. Try to do as follows within the for: email == user.value.email.
I have an activity which receives an intent with a putExtra from other activity.
And I want to create a SharedPreference each time the activity receives the putExtra value, in this case a String so I can show all the Strings stored and show in a TextView without loosing the previous String shown.
tvTextView = (TextView)findViewById(R.id.tvTextView);
Bundle extras = getIntent().getExtras();
linearLayout = (LinearLayout)findViewById(R.id.linearLayout);
if (extras != null) {
newNote = extras.getString("Note");
Button noteButton = new Button(this);
noteButton.setText(newNote);
linearLayout.addView(noteButton);
// and get whatever type user account id is
SharedPreferences prefs = getSharedPreferences("MisPreferencias",getApplication().MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("newNote", note);
editor.commit();
String note = prefs.getString("newNote", "Welcome");
tvDiario.setText(note);
This is my code but it only saves the last string I want to show a string and then when I get a different String from intent show it but keep showing the previous, as a story. I need to edit the SharedPreference with different values each time the activity receive the putExtra data.
I don't think you fully understand SharedPreferences; it's a key-value data storage. By calling:
editor.putString("newNote", note);
you always override your saved value under the newNote key by new value note. editor.putString does not append your new data to your stored data, it rewrites the data.
The solution: you need to get your stored data first, append new data to those stored data, and store the updated data. Try:
newNote = extras.getString("Note");
...
SharedPreferences prefs = getSharedPreferences("MisPreferencias", getApplication().MODE_PRIVATE);
String storedNotes = prefs.getString("notes", "");
SharedPreferences.Editor editor = prefs.edit();
editor.putString("notes", storedNotes + newNote + "\n");
editor.commit();
String notes = prefs.getString("notes", "");
tvDiario.setText(notes);
I exchanged your newNote key by notes to better describe what is actually stored. I also recommend to read on documentation of Editor.putString and SharedPreferences.getString, I feel like you don't have a clear idea of the interface yet.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Summary:
Goal: create a dynamic table of contents on start
Expected results: if the user clicks button that corresponds to page x, the user will be directed to page x
Actual results: if the user clicked button that corresponds to page x, the user will be directed to the last page
What I have tried:
Followed the code for OnClick events listed on the MRTK documents https://microsoft.github.io/MixedRealityToolkit-Unity/Documentation/README_Interactable.html
public static void AddOnClick(Interactable interactable)
{
interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}
Looked into GitHub thread https://github.com/microsoft/MixedRealityToolkit-Unity/issues/4456
Looked into the GitHub thread https://github.com/microsoft/MixedRealityToolkit-Unity/issues/5013
Code: TOC = Table of Contents
private void TOCpage()
{
GameObject TOC = new GameObject(); // holds table of contents buttons
for(int i = 1; 1 <= pages.Count - 1; i++)
{
GameObject TOCgameObject = (GameObject)Instantiate(TOCButtonPrefab);
var TOCButton = TOCgameObject.GetComponent<Interactable>();
TOCbutton.OnClick.AddListener(() => TaskOnClick(i));
}
}
public void TaskOnClick(int TOCButtonNumber)
{
Debug.Log("Table of contents button number " + TOCButtonNumber + " clicked");
}
If user clicks on TOCbutton for page 1, and there are 7 pages, the user is directed to page 7.
TOCbutton.OnClick.AddListener(() => TaskOnClick(i));
This happens because i is not local to the lambdas, but is defined in the outer scope, and it is accessed when the lambda is called — not when it is defined. At the end of the loop, the value of i is 7, so all the functions log 7.
Instead, you can create a local variable within the loop and assign it the value of the iteration variable or use foreach statement to do it under C#5.0 or later.
As a solution, you can refer to the following code:
foreach (var i in Enumerable.Range(1, pages.Count))
{
GameObject TOCgameObject = (GameObject)Instantiate(TOCButtonPrefab);
var TOCButton = TOCgameObject.GetComponent<Interactable>();
TOCbutton.OnClick.AddListener(() => TaskOnClick(i));
}
This question already has answers here:
Validating input using java.util.Scanner [duplicate]
(6 answers)
Closed 5 years ago.
Is it possible to implement the commented lines in order to distinguish between an Integer and a String when a user inputs said value into the console? The code works with the rest of my program, but I want the user to be able to input the Employee ID (an int) in addition to name and/or address.
public void query(){
String newValue;
System.out.println("Please enter the name, address, or employee "
+ "ID you are looking for");
Scanner input = new Scanner(System.in);
//if (Integer.parseInt(input);
//newValue = input.nextInt();
//else
newValue = input.nextLine();
input.close();
if (name.equals(newValue) | address.equals(newValue) )
System.out.println(toString());
else System.out.println("There is no employee with that name, address, or ID");
}
Yes, you can do that using isNumeric and isAlpha methods of StringUtils class from Apache Commons library.
I have an Access database which I need to retrieve all fields except the first and last and display it in a JTable. Everything works perfectly fine when I create my Object[][] but when i return it, i get a NullPointerException. I tried to find where there could be a null value in the database by printing the whole object out but that works fine and no values are null. Why would returning the Object[][] give me a NullPointerException and how can i fix it?
the stack trace is:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
public Object [] [] SetTrainingLogTable() throws SQLException
{
DatabaseConnection connection = new DatabaseConnection();
//Retrieves all the data from the TrainingLog table
ResultSet resultset = connection.SelectStatements("SELECT * FROM TrainingLog");
//Retrieves the number of entries
ResultSet numberofworkouts = connection.SelectStatements("SELECT COUNT(*) FROM TrainingLog");
int count = numberofworkouts.getInt(1);
number = count;
String[][] table = new String [count] [6];
//Number to incriment for while loops
int row = 0;
String date = "";
while(row<count)
{
date = resultset.getString(2);
table [row][0] = calculate.RefineDate(date);
table [row][1] = resultset.getString(3);
table [row][2] = resultset.getString(4);
table [row][3] = resultset.getString(5);
table [row][4] = resultset.getString(6);
table [row][5] = resultset.getString(7);
resultset.next();
row++;
}
Object[][] data = table;
connection.close();
return data;
}
I ran a debugger and it only gives the error when the return line is run.
It's best to post the stack trace and tell which line is raising the error. However, the typical way of writing such code is:
Connection con = ...;
Statement st = ...;
ResultSet rs = ...;
while (rs.next()) {
// ...
}
The result set starts out pointing before the first row. rs.next() returns whether there is a next row, and advances to it if it exists. Can you rewrite it in that style?
Other suggestions:
Can you create an actual object type instead of using Object[] to store the data from each row? Call it Workout.
Can you use a List<Workout> instead of your Object[][]?
Is the date stored in the database as a SQL DATE or TIMESTAMP? Then, don't convert it to a Java String: use java.sql.Date or java.util.Date. At work, I have a large old program that uses strings for dates, and it uses different formats to convert the values at different times. It's pretty miserable.
Don't use SELECT *. Give the names of the columns to return. Use the rs.getString("column_name") syntax.
There's no need to set one variable to the returned table and immediately set another variable to it.
Closing the connection or statement should be done in a finally block, or by try-with-resources.