Shared prefrence overwrites - android

I save a string set in shared preferences that loads to my watchlist. When the user clicks on a button, in the movie's page, it takes the movie's name, title and release date and store them in a JSON object. All of them are stored as String. The problem persists when I try to add a movie in the watchlist, each new movie I add, the last movie gets overwritten, which means I can only have one movie in my watchlist at all time.
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences sharedPreferences = getSharedPreferences("WatchlistData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
JSONObject obj = new JSONObject();
try {
obj.put("name", name);
obj.put("date", releaseDate);
obj.put("platform", platform);
} catch (JSONException e) {
e.printStackTrace();
}
Set<String> set = new HashSet<String>();
set.add(obj.toString());
editor.putStringSet("setOfStrings", set);
editor.commit(); //saved
}
});
Watchlist fragment OnCreateView
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_watchlist, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.watchlist);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mWatchlistAdapter = new WatchlistAdapter(getActivity(), loadFromStorage());
mWatchlistAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mWatchlistAdapter);
return view;
}
The loadFromStorage, loads my xml file in the recyclerview, this method is passed in my adapter constructor.
SharedPreferences mPrefs = getActivity().getSharedPreferences("WatchlistData", Context.MODE_PRIVATE);
ArrayList<watchlist> items = new ArrayList<watchlist>();
Set<String> set = mPrefs.getStringSet("setOfStrings", null); //retrieving set of strings
if (set == null){
Toast.makeText(getActivity(), "No data found", Toast.LENGTH_LONG).show();
} else {
//for every string in set
for (String s : set) {
try {
JSONObject jsonObject = new JSONObject(s); //for every JSONObject String
String name = jsonObject.getString("name");
String date = jsonObject.getString("date");
String platform = jsonObject.getString("platform");
watchlist newGame = new watchlist();
newGame.setGame(name);
newGame.setDate(date);
newGame.setPlatform(platform);
items.add(newGame);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
return items;
}

By default SharedPreferences replaces the old data with the newer one. What you can do is, get the old data first then append with with the newer one,
//Extract the value stored in SharedPreferences
String value = prefs.getString(<Key>, <DefaultValue>);
//Append to the extracted value
String appendedValue = append(value, newValue);
//Write the result back to SharedPreferences
editor.putString(<Key>, appendedValue).commit();
SharedPreferenced are made for lite weight data but not for heavy storage. So, according to your requirement you should write the data to a JSON/XML file in the external storage and read it back later.

it looks like you are just overwriting the stringset in SharedPreferences every time you put something there, which is why you only ever see the last result:
Set<String> set = new HashSet<String>();
set.add(obj.toString());
editor.putStringSet("setOfStrings", set);
You are just created a new 'set' on each click and saving that to "setOfStrings".
I was considering a similar implementation myself for a project, but saw that it became an issue manipulating the StringSet from SharedPreferences. For reference, [documentation on Android developers site](http://developer.android.com/reference/android/content/SharedPreferences.html#getStringSet(java.lang.String, java.util.Set))
states,
"Note that you must not modify the set instance returned by this call. The consistency of the stored data is not guaranteed if you do, nor is your ability to modify the instance at all."
There are workarounds to this, but from what I understand it is better to avoid using SharedPreferences for data such as this which will be manipulated often, as it is just saved as an xml file prone to issues- you may want to consider implementing that information in a SQLite database.

Related

SharedPreferences not saving boolean attribute

I am facing an issue with saving an object boolean in SharedPreferences. The object (part of ArrayList "questions") contains a boolean "recentAnswer".
If I change the boolean value and want to use it in another activity, the value is still the old one.
Here is my saveData-method from Activity 1:
private void saveData(){
SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(questions);
editor.putString("task list", json);
editor.apply();
}
and here's where I use it in order to save the changed boolean value (Activity 1):
private void checkAnswer(Button answerButton){
if (answerButton.getText().equals(questions.get(currentQuestion).getAnswer1())){
questions.get(currentQuestion).recentAnswer = true;
}
else{
questions.get(currentQuestion).recentAnswer = false;
}
Toast.makeText(this, Boolean.toString(questions.get(currentQuestion).recentAnswer), Toast.LENGTH_SHORT).show();
saveData();
}
Firstly, I load the ArrayList in Activity 2:
private void loadData(){
SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("task list", null);
Type type = new TypeToken<ArrayList<Question>>(){}.getType();
questions = gson.fromJson(json, type);
if(questions == null){
questions = new ArrayList<>();
}
}
And then I want to get the "recentAnswer" values (Activity 2):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_statistics);
loadData();
for (Question element : questions){
int recentWrong;
if (!element.recentAnswer){
recentWrong++;
}
}
Toast.makeText(this, Integer.toString(recentWrong), Toast.LENGTH_SHORT).show();
}
No matter, how I change the values in Activity 1, in Activity 2 "recentWrong" is always = 0, even though I am accessing the questions.
Don't do this:
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(questions);
editor.putString("task list", json);
Do not do this ever. First off is you are not checking and do not know what the value questions may hold and you also should not save something like that in SharedPrefs.
If you have several questions, then save each question together with its response in SharedPrefs and if you need to save an answer that you want to check against later in code, use string values stored in the res->strings.xml.
If the question is too long, find a way to concat it or use the res->string-arrays.xml and keep the questions there, then reference them from there.
You need to go back a bit and take a look at how to design programs in Java, Kotlin or any language for that matter. This is what comes after you learn programming basics.

save the button was click and display the option with date as summary in android app

choose which diaper is chosen and record the date and time, every time a diaper is changed then save it.
I tried to use shared preference but i do not really know how to use it properly as I am completely new to this.
Try This
Define an Array list in which you will save your date time
SharedPreferences sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
List<Date> dateList = new ArrayList<>();
Then on diaper change function try this
public void onDiaperChange(Date date){
if(sharedpreferences.contains("DateList")){
dateList = sharedpreferences.getString("DateList","");
}
dateList.add(date);
sharedpreferences.putString(ObjectSerializer.serialize(dateList));
}
and to get the list use this
public void getAllDateTime(){
List<Date> fetchedData = new ArrayList<>();
fetchedData = (ArrayList<Date>) ObjectSerializer.deserialize(prefs.getString("DateList", ObjectSerializer.serialize(new ArrayList<Date>())));
} catch (IOException e) {
}
you can get ObjectSerializer from here ObjectSerializer
Use Realm to store data in database
To store data is like
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
DateModel datemodel = realm.createObject(DateM.class);
datemodel.setDate(your date);
realm.commitTransaction();
Get stored data :
RealmResults< DateModel > result = realm.where(DateModel.class)
.findAll();

As simple as saving a Hashset in the SharedPrefs

I was trying to write a simple method for my android application. This method should find an integer [0-49] that isn't contained in a HashSet. Afterward should save the HashSet in the sharedPrefs using the putStringSet() method. Below I provide the code I have written.
HashSet aHashSet;
SharedPreferences sharedPreferences;
int id;
sharedPreferences = getSharedPreferences("prefs", MODE_PRIVATE);
aHashSet = (HashSet) sharedPreferences.getStringSet("aHashSet", null);
if (aHashSet == null)
aHashSet = new HashSet();
for (id = 0; id < 50; ++id) {
if (aHashSet.contains(id))
continue;
else {
aHashSet.add(id);
break;
}
}
Log.d("myClassName", String.valueOf(sharedPreferences.edit().putStringSet("aHashSet", aHashSet).commit()));
return id;
I have checked the logs every time I add something to the set and save it in the shredPrefs I get a true (as a successful) commit. While this worked fine while the app was running, After the application was closed the HashSet wasn't saved correctly, and the starting number was always 0.
So I tried to debug this, I thought that I'll use a String and I will append the numbers to it and then save it, in order to check if the problem is that I cannot save the Hashset correctly, so I add this logic as below.
HashSet<String> aHashSet;
int id;
aHashSet = (HashSet) sharedPreferences.getStringSet("aHashSet", null);
String checkingString = sharedPreferences.getString("cs","");
if (aHashSet == null)
aHashSet = new HashSet();
for (id=0;id<50;++id){
if(aHashSet.contains(String.valueOf(id)))
continue;
else{
aHashSet.add(String.valueOf(id));
break;
}
}
checkingString+= id;
Log.d("myClassName",String.valueOf(sharedPreferences.edit().putStringSet("aHashSet",aHashSet).commit()));
Toast.makeText(this, checkingString, Toast.LENGTH_SHORT).show();
sharedPreferences.edit().putString("cs",checkingString).commit();
return id;
Now what I was expecting to see was: the checkingString to be appended and saved correctly, but the HashSet to lose the added values every time the app is restarted. However, now everything worked as it should, the HashSet was saved and restored correctly every time the app was restarted. Can someone explain to me how is this possible? the only change I did was to add another string to the sharedPrefs, how could this influence the HashSet? Thank you for your time
Hope this will help you. For this type of problem I have made two function for storing and retrieving multiple value using Hashmap
Store data into preference
public static void storePreference(HashMap<String, String> parameters) {
SharedPreferences.Editor editor = ManageMyAppsApplication.sharedPref
.edit();
Iterator<Map.Entry<String, String>> it = parameters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pairs = it.next();
editor.putString((String) pairs.getKey(), (String) pairs.getValue());
}
editor.commit();
}
Retrieving data from preference
public static HashMap<String, String> getPreference(String[] keys) {
HashMap<String, String> parameters = new HashMap<String, String>();
for (String key : keys) {
parameters.put(key,
ManageMyAppsApplication.sharedPref.getString(key, null));
}
return parameters;
}

SharedPreferences not saving all the data after restart

I am new to Android App Development and I am supposed to make a TodoList App for a course. But the SharedPreference in my code is not working. I dont know if I'm supposed to use it in a specific way in a specific method like onCreate or onStop.
It is saving the first input the user is entering permanently, but in the same position:
(The "task0" is what I used to track the different variable names I used as argument for "putString" in addStuff method, to avoid replacing values)
It is saving the inputs after that in the same session, but if the user ends that session, all those values after "t" are gone. If the user restarts the app and inputs something else (like "g"), it is saving "g" in that same 3rd position.
I have basic Java knowledge and I tried to understand what is going on using it, but failed. Please let me know where is the mistake and how to use SharedPreferences properly.
public class TodoActivity extends AppCompatActivity {
public ArrayList<String> items;
public ArrayAdapter<String> itemsAdapter;
public ListView list;
public String s;
public EditText taskBox;
public static final String filename = "itemsList";
public TextView text;
public static int counter = 0;//counter starting at 0 no matter what, everytime the app starts
public String newtask= "task";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_todo);
list = (ListView) findViewById(R.id.list1);text = (TextView) findViewById(R.id.text1);
taskBox = (EditText) findViewById(R.id.box);
s = taskBox.getText().toString();
items = new ArrayList<String>();
itemsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
list.setAdapter(itemsAdapter);
//add items to list
items.add("First Item");
items.add("Second Item");
//restore
SharedPreferences sp = this.getSharedPreferences("itemsList", 0);
//checking if it stores the previous values, this gives the last input but not the previous ones after restarting the app
String dummyname = "task";
text.setText(String.valueOf(counter));//since counter is again at
for(int c=0; c<=50; c++){
String num = String.valueOf(c);
dummyname = dummyname + num;
String x = sp.getString(dummyname, "not found");
if (x.equalsIgnoreCase("not found")){
counter=c-1;
break;
} else {
items.add(x);
text.setText(dummyname);
}
}
}
public void addItem(View v){
s = taskBox.getText().toString();
itemsAdapter.add(s);//adding the new task as string
String temp = String.valueOf(counter);
newtask = "task" + temp;
//trying to store the new tasks with different variable names to avoid being replaced
text.setText(newtask);
SharedPreferences sp = this.getSharedPreferences("itemsList", 0);
SharedPreferences.Editor e = sp.edit();
e.putString(newtask,s);
e.apply();
counter++;
}
}
If you have relatively small collection of key-values that you would like to save,
You should use Shared preference API
Read from the shared preference:
Pass the key and value you want to write,create a SharedPreferences.Editor by calling edit() on your SharedPreferences.
Pass key and values you want to save by using this method putInt() ,putString() ,Then call commit() to save the changes. For example:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("KeyName", newHighScore);
editor.commit();
Write from the shared preference:
To retrieve values from a shared preferences file, call methods such as getInt() and getString(),
providing the key for the value you want, and optionally a default value to return if the key isn't present. For example:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt("KeyName", defaultValue);
Two things :
1) To initialize SharedPreferences use :
sharedPreferences = getSharedPreferences("itemsList", Context.MODE_PRIVATE);
2) Where are you calling addItem() method??
The problem is about the Tag you use to save items. See this Line :
dummyname = dummyname + num;
You add item by this format :
task0
task1
task2
but you are getting values in this format
task0
task01
task012
Just change these two line of code :
//dummyname = dummyname + num;
//String x = sp.getString(dummyname, "not found");
String newDummy= dummyname + num;
String x = sp.getString(newDummy, "not found");

Adding an item to arralist which is already saved in shared preferences in android

I am having an array list which is already stored in shared preferences.I want to add another item in array list.
Whenever i am trying to add an item in array list it is removing all the previous data stored in arraylist
How can i add item without removing the previous data in shared preferences
ArrayList<String> cartArrayListID,cartArrayListName,cartArrayListPrice,cartArrayListImage;
String cartID,cartName,cartPrice,cartImage;
cartArrayListID=new ArrayList<>();
cartArrayListName=new ArrayList<>();
cartArrayListPrice=new ArrayList<>();
cartArrayListImage=new ArrayList<>();
cartArrayListID.add(cartID);
cartArrayListName.add(cartName);
cartArrayListPrice.add(cartPrice);
cartArrayListImage.add(cartImage);
SharedPreferences sprefCart=getSharedPreferences("CARTINFO", Context.MODE_PRIVATE);
SharedPreferences.Editor editorCart=sprefCart.edit();
Gson gson = new Gson();
String id_=gson.toJson(cartArrayListID);
String name_=gson.toJson(cartArrayListName);
String price_=gson.toJson(cartArrayListPrice);
String image_=gson.toJson(cartArrayListImage);
editorCart.putString("ID", id_);
editorCart.putString("NAME", name_);
editorCart.putString("PRICE", price_);
editorCart.putString("IMAGE", image_);
editorCart.apply();
Toast.makeText(ProductActivity.this, "Added to cart", Toast.LENGTH_SHORT).show();
as I see in your code, you create a whole new ArrayLists cartArrayListID, cartArrayListName , ..etc everytime, and then you put the new value into it, after that you save it in SharedPreferences which in turn will replace the old one saved in it with your new one, so you have to:
get the corresponding ArrayList from Shared preferences at first.(for ex. cartArrayListName)
save it in a new array called cartArrayListID.
put the new values in this new array.
save it back in SharedPreferences.
You cannot get an ArrayList from SharedPreferences.
You can get a Set using getStringSet. Notice that the jdoc states that
Note that you must not modify the set instance returned by this call.
so do something like:
Set<String> mySet = new HashSet(yourPrefDataCollection);
mySet.add("some string");
sp.edit().putStringSet("your set key", mySet).commit();
Use GSON to get ArrayList from the String.
Add some items.
Try this example to save ArrayList to String, so you can store to SharedPreferences.
If your ArrayList has some special type (not String), use this construction:
ArrayList<Foo> list = new Gson().fromJson(
gsonString, new TypeToken<List<Foo>>(){}.getType());
The best way to accomplish this is by storing your array as a String in JSON format. You have to create a simple POJO to store your array and the rest is simple. See example below;
public void saveArray(List<String> yourArray) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("YOUR_ARRAY_KEY", new Gson().toJson(new ArrayListHolder(yourArray)));
editor.apply();
}
public List<String> getArray() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
String arrayJson = sharedPreferences.getString("YOUR_ARRAY_KEY", null);
if (arrayJson != null) {
return new Gson().fromJson(arrayJson, ArrayListHolder.class).getYourArray();
}
return null;
}
private class ArrayListHolder {
private List<String> yourArray;
public ArrayListHolder(List<String> yourArray) {
this.yourArray = yourArray;
}
public List<String> getYourArray() {
return yourArray;
}
public void setYourArray(List<String> yourArray) {
this.yourArray = yourArray;
}
}

Categories

Resources