New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

save Set<String> Is someone using this? -> YES PLEASE! #7

Open
enkemari opened this Issue May 4, 2015 · 12 comments

Comments

Projects
None yet
8 participants
@enkemari
Copy link

enkemari commented May 4, 2015

Hi,

In the "Missing Features" section you ask if someone wants to save Set - yes, I do!

Well, actually more saving a Map or an ArrayList<Map<String, Object>> - that's what I work with mostly. So I would very often need to save something like this as the value to some key:

[
   {
      "key": "value",
      "key2": 222,
      "key3": {"sub_key":"sub_value", "sub_key2":23232},
      "key4": [1,2,3,4],
      "key5": "etc"
   }
]

I've had to use a combination of Base64OutputStream, ByteArrayOutputStream and ObjectOutputStream to save objects to shared prefs. :\

@franciscerio

This comment has been minimized.

Copy link

franciscerio commented May 4, 2015

up

@passsy passsy added this to the future release milestone May 4, 2015

@passsy passsy added the enhancement label May 4, 2015

@passsy

This comment has been minimized.

Copy link
Member

passsy commented May 4, 2015

I see the benefit of saving Lists or Sets. But I think saving complex "json" structures is out of the scope for this library.

You could easily use gson to create a string representative of your object and save it into Tray and parse it again with gson.

@ubeyou

This comment has been minimized.

Copy link

ubeyou commented Oct 2, 2015

up, have been using Set with SharedPreference, would like to see this feature in 1.0

@KioKrofovitch

This comment has been minimized.

Copy link

KioKrofovitch commented Jul 12, 2016

Upvote! I would like to be able to use a regular String Set as well

@domenukk

This comment has been minimized.

Copy link

domenukk commented Sep 23, 2016

I want to add it would be great to not only put and get StringSets but also to append to StringSets atomically.
The Android SharedPrefs are missing this function afaik so right now we lock, get the current set, append something and then write the new value back. Locking is not possible in a multiprocess app. (Unless we start having a "locked" preference and listen for a value change, but then this is getting out of hand 🎯)

@eyedol

This comment has been minimized.

Copy link
Contributor

eyedol commented Oct 20, 2016

A simple trick like this 1 could get you to save the Set as a serialized JSON string into Tray as mentioned by @passsy

@eyedol

This comment has been minimized.

Copy link
Contributor

eyedol commented Oct 22, 2016

@passsy I'm wondering if this issue is still valid? I would like to work on it if you're open to extending the scope of this library. If it's going to stretch the scope a bit, I could make it a module( something like tray-converters ) on it own that could be installed as an extra dependency for users who wants to save complex object with tray. This will complement tray itself.

With the extra module approach, I could generalize it so people can use whatever serialization libraries they like; like Gson, Moshi, Jackson, etc. I would support these three with Gson being the default.

Rough sample usage will be in the form:

TrayConverter trayConverter = new TrayConverter.Builider()
     // This will override the default converter
    .setConverter(MoshiConverter())
    .build();

// To convert object to JSON string
String json = trayConverter.serialize(model);

final AppPreferences appPreferences = new AppPreferences(getContext());
appPreferences.put("key", jsonString);

// To convert JSON string back to object,
final String value = appPreferences.getString("key", null);

Model model = trayConverter.deserialize(value, Model.class);

I see people will appreciate this if tray supports saving complex object without having to do a lot of extra work. I'm judging based on the +1s on this issue. Let me know what you think.

@domenukk

This comment has been minimized.

Copy link

domenukk commented Oct 22, 2016

@eyedol keep one thing in mind though: if objects would be supported there should be a locking mechanism or transactions (or some async wait for lock queue) for them. Else it's pretty useless, at least for me.

@eyedol

This comment has been minimized.

Copy link
Contributor

eyedol commented Oct 24, 2016

@domenukk thanks for chipping in. I'm curious how you currently save objects. What I'm proposing will be independent of Tray. It just gives Tray a string value to save or expect a string value from it to parse. I don't think async, wait, or locks will be necessary in my implementation.

@domenukk

This comment has been minimized.

Copy link

domenukk commented Oct 24, 2016

@eyedol depends on your use case of course. If you want exactly one process (like a receiver) to save and n processes to read then this approach is fine but it opens the door for people to shoot themselves in the foot. As soon as you want to change an object you start having race conditions. For String Sets right now I use old school shared preferences and put the 'insert into' and 'get' methods in synchronized blocks. Having this option in Tray somehow would be great.
If you start messing with objects you might want to consider a proper db like realm.
That being said if you want to do it, do it.

@eyedol

This comment has been minimized.

Copy link
Contributor

eyedol commented Oct 26, 2016

@domenukk thanks for sharing your insight and current approach to the problem. I was of the inclination that people were interested in saving the object as a serialized JSON string( with Tray supporting strings ) hence why I proposed this approach. If it will cause more issues than good then no need. I was hoping to hear a perspective from the project maintainers but not yet. Hopefully soon.

Anyway, I made this into a standalone Java library instead. More so like a wrapper around the serializers out there. It's in the same vain as I proposed above. This way, I felt it won't mess too much with the core project.

@Cilenco

This comment has been minimized.

Copy link

Cilenco commented Dec 24, 2017

This would also be great for the new PreferenceDataStore class because we have to implement getStringSet. With this we can tell Preferences to use this storage implementation in the background by calling:

PreferenceManager pm = getPreferenceManager();
pm.setPreferenceDataStore(new SettingsDataStore(getContext()));

on a PreferenceFragmentCompat (here SettingsDataStore is a subclass of PreferenceDataStore).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment