Skip to content

Commit ccf9742

Browse files
committed
Merge pull request androidannotations#962 from WonderCsabo/264_sharedpref_string_set
SharefPref StringSet implementation
2 parents 8bcb94b + 311e6e9 commit ccf9742

File tree

14 files changed

+339
-22
lines changed

14 files changed

+339
-22
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.annotations.sharedpreferences;
17+
18+
import java.lang.annotation.ElementType;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
import java.lang.annotation.Target;
22+
23+
import org.androidannotations.annotations.ResId;
24+
25+
/**
26+
* Use on methods in {@link SharedPref} annotated class. The generated method
27+
* will return an empty {@link java.util.Set} of Strings by default.
28+
* <p/>
29+
* The key of the preference will be the method name by default. This can be
30+
* overridden by specifying a string resource with the {@link #keyRes()}
31+
* parameter.
32+
* <p/>
33+
* <b>Implementation note:</b>
34+
* <p/>
35+
* Since {@code SharedPreferences.getStringSet} is only available from API 11,
36+
* the generated method serializes the {@code Set<String>} into a {@code String}
37+
* , and persists it with
38+
* {@link android.content.SharedPreferences.Editor#putString(String, String)
39+
* SharedPreferences.Editor#putString(String, String)} using API 10 and below.
40+
* From API 11 and up, the generated method simply uses the native
41+
* {@link android.content.SharedPreferences SharedPreferences}
42+
* {@code Set<String>} methods.
43+
*/
44+
@Retention(RetentionPolicy.CLASS)
45+
@Target(ElementType.METHOD)
46+
public @interface DefaultStringSet {
47+
48+
int keyRes() default ResId.DEFAULT_VALUE;
49+
}

AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/api/sharedpreferences/EditorHelper.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ protected StringPrefEditorField<T> stringField(String key) {
4747
return new StringPrefEditorField<T>(cast(), key);
4848
}
4949

50+
protected StringSetPrefEditorField<T> stringSetField(String key) {
51+
return new StringSetPrefEditorField<T>(cast(), key);
52+
}
53+
5054
protected BooleanPrefEditorField<T> booleanField(String key) {
5155
return new BooleanPrefEditorField<T>(cast(), key);
5256
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.api.sharedpreferences;
17+
18+
import java.io.IOException;
19+
import java.io.StringReader;
20+
import java.io.StringWriter;
21+
import java.util.Collections;
22+
import java.util.Set;
23+
import java.util.TreeSet;
24+
25+
import org.xmlpull.v1.XmlPullParser;
26+
import org.xmlpull.v1.XmlPullParserException;
27+
import org.xmlpull.v1.XmlSerializer;
28+
29+
import android.util.Log;
30+
import android.util.Xml;
31+
32+
public final class SetXmlSerializer {
33+
34+
private static final String NAMESPACE = "";
35+
private static final String STRING_TAG = "AA_string";
36+
private static final String SET_TAG = "AA_set";
37+
38+
private SetXmlSerializer() {
39+
40+
}
41+
42+
public static String serialize(Set<String> set) {
43+
if (set == null) {
44+
set = Collections.emptySet();
45+
}
46+
47+
StringWriter writer = new StringWriter();
48+
XmlSerializer serializer = Xml.newSerializer();
49+
50+
try {
51+
serializer.setOutput(writer);
52+
serializer.startTag(NAMESPACE, SET_TAG);
53+
54+
for (String string : set) {
55+
serializer.startTag(NAMESPACE, STRING_TAG) //
56+
.text(string) //
57+
.endTag(NAMESPACE, STRING_TAG);
58+
}
59+
60+
serializer.endTag(NAMESPACE, SET_TAG) //
61+
.endDocument();
62+
63+
} catch (IllegalArgumentException e) {
64+
65+
} catch (IllegalStateException e) {
66+
67+
} catch (IOException e) {
68+
69+
}
70+
71+
return writer.toString();
72+
}
73+
74+
public static Set<String> deserialize(String data) {
75+
Set<String> stringSet = new TreeSet<String>();
76+
XmlPullParser parser = Xml.newPullParser();
77+
78+
try {
79+
parser.setInput(new StringReader(data));
80+
parser.next();
81+
parser.require(XmlPullParser.START_TAG, NAMESPACE, SET_TAG);
82+
83+
while (parser.next() != XmlPullParser.END_TAG) {
84+
parser.require(XmlPullParser.START_TAG, NAMESPACE, STRING_TAG);
85+
86+
parser.next();
87+
parser.require(XmlPullParser.TEXT, null, null);
88+
stringSet.add(parser.getText());
89+
90+
parser.next();
91+
parser.require(XmlPullParser.END_TAG, null, STRING_TAG);
92+
}
93+
} catch (XmlPullParserException e) {
94+
Log.w("getStringSet", e);
95+
return null;
96+
} catch (IOException e) {
97+
Log.w("getStringSet", e);
98+
return null;
99+
}
100+
101+
return stringSet;
102+
}
103+
}

AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/api/sharedpreferences/SharedPreferencesCompat.java

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,74 @@
1717

1818
import java.lang.reflect.InvocationTargetException;
1919
import java.lang.reflect.Method;
20+
import java.util.Set;
2021

2122
import android.content.SharedPreferences;
22-
import android.content.SharedPreferences.Editor;
2323

2424
/**
25-
* Reflection utils to call SharedPreferences$Editor.apply when possible,
26-
* falling back to commit when apply isn't available.
25+
* Reflection utils to call most efficient methods of SharedPreferences and
26+
* SharedPreferences$Editor or fall back to another implementations.
2727
*/
2828
public abstract class SharedPreferencesCompat {
2929

3030
private SharedPreferencesCompat() {
3131
}
3232

33-
private static final Method sApplyMethod = findApplyMethod();
33+
private static final Method sApplyMethod = findMethod(SharedPreferences.Editor.class, "apply");
34+
private static final Method sGetStringSetMethod = findMethod(SharedPreferences.class, "getStringSet", String.class, Set.class);
35+
private static final Method sPutStringSetMethod = findMethod(SharedPreferences.Editor.class, "putStringSet", String.class, Set.class);
3436

35-
private static Method findApplyMethod() {
37+
public static void apply(SharedPreferences.Editor editor) {
38+
try {
39+
invoke(sApplyMethod, editor);
40+
return;
41+
} catch (NoSuchMethodException e) {
42+
editor.commit();
43+
}
44+
}
45+
46+
public static Set<String> getStringSet(SharedPreferences preferences, String key, Set<String> defValues) {
3647
try {
37-
Class<Editor> cls = SharedPreferences.Editor.class;
38-
return cls.getMethod("apply");
48+
return invoke(sGetStringSetMethod, preferences, key, defValues);
49+
} catch (NoSuchMethodException e) {
50+
String serializedSet = preferences.getString(key, null);
51+
return SetXmlSerializer.deserialize(serializedSet);
52+
}
53+
}
54+
55+
public static void putStringSet(SharedPreferences.Editor editor, String key, Set<String> values) {
56+
try {
57+
invoke(sPutStringSetMethod, editor, key, values);
58+
} catch (NoSuchMethodException e1) {
59+
editor.putString(key, SetXmlSerializer.serialize(values));
60+
}
61+
}
62+
63+
private static Method findMethod(Class<?> clazz, String name, Class<?>... parameterTypes) {
64+
try {
65+
return clazz.getMethod(name, parameterTypes);
3966
} catch (NoSuchMethodException unused) {
4067
// fall through
4168
}
4269
return null;
4370
}
4471

45-
public static void apply(SharedPreferences.Editor editor) {
46-
if (sApplyMethod != null) {
47-
try {
48-
sApplyMethod.invoke(editor);
49-
return;
50-
} catch (InvocationTargetException unused) {
51-
// fall through
52-
} catch (IllegalAccessException unused) {
53-
// fall through
54-
}
72+
@SuppressWarnings("unchecked")
73+
public static <T> T invoke(Method method, Object obj, Object... args) throws NoSuchMethodException {
74+
if (method == null) {
75+
throw new NoSuchMethodException();
76+
}
77+
78+
try {
79+
return (T) method.invoke(obj, args);
80+
} catch (IllegalAccessException e) {
81+
// fall through
82+
} catch (IllegalArgumentException e) {
83+
// fall through
84+
} catch (InvocationTargetException e) {
85+
// fall through
5586
}
56-
editor.commit();
87+
88+
throw new NoSuchMethodException(method.getName());
5789
}
5890
}

AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/api/sharedpreferences/SharedPreferencesHelper.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.androidannotations.api.sharedpreferences;
1717

18+
import java.util.Set;
19+
1820
import android.content.SharedPreferences;
1921

2022
public abstract class SharedPreferencesHelper {
@@ -41,6 +43,10 @@ protected StringPrefField stringField(String key, String defaultValue) {
4143
return new StringPrefField(sharedPreferences, key, defaultValue);
4244
}
4345

46+
protected StringSetPrefField stringSetField(String key, Set<String> defaultValue) {
47+
return new StringSetPrefField(sharedPreferences, key, defaultValue);
48+
}
49+
4450
protected BooleanPrefField booleanField(String key, boolean defaultValue) {
4551
return new BooleanPrefField(sharedPreferences, key, defaultValue);
4652
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.api.sharedpreferences;
17+
18+
import java.util.Set;
19+
20+
public final class StringSetPrefEditorField<T extends EditorHelper<T>> extends AbstractPrefEditorField<T> {
21+
22+
StringSetPrefEditorField(T editorHelper, String key) {
23+
super(editorHelper, key);
24+
}
25+
26+
public T put(Set<String> value) {
27+
SharedPreferencesCompat.putStringSet(editorHelper.getEditor(), key, value);
28+
return editorHelper;
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.api.sharedpreferences;
17+
18+
import java.util.Set;
19+
20+
import android.content.SharedPreferences;
21+
22+
public final class StringSetPrefField extends AbstractPrefField {
23+
24+
private final Set<String> defaultValue;
25+
26+
StringSetPrefField(SharedPreferences sharedPreferences, String key, Set<String> defaultValue) {
27+
super(sharedPreferences, key);
28+
this.defaultValue = defaultValue;
29+
}
30+
31+
public Set<String> get() {
32+
return getOr(defaultValue);
33+
}
34+
35+
public Set<String> getOr(Set<String> defaultValue) {
36+
return SharedPreferencesCompat.getStringSet(sharedPreferences, key, defaultValue);
37+
}
38+
39+
public void put(Set<String> value) {
40+
SharedPreferences.Editor editor = sharedPreferences.edit();
41+
SharedPreferencesCompat.putStringSet(editor, key, value);
42+
apply(editor);
43+
}
44+
}

0 commit comments

Comments
 (0)