Skip to content

Commit 7ca7800

Browse files
committed
Implements a mechanism to save the rates every time they are updated.
1 parent 45efc94 commit 7ca7800

9 files changed

Lines changed: 567 additions & 35 deletions

File tree

app/build.gradle

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ buildscript {
77
}
88
}
99

10+
repositories {
11+
maven { url = "https://oss.sonatype.org/content/repositories/snapshots" }
12+
}
13+
1014
apply plugin: 'com.android.application'
1115
apply plugin: 'com.neenbedankt.android-apt'
1216

@@ -45,6 +49,7 @@ dependencies {
4549
apt 'com.google.dagger:dagger-compiler:2.0'
4650
provided 'javax.annotation:jsr250-api:1.0'
4751

48-
testCompile "junit:junit:4.12"
49-
testCompile "org.mockito:mockito-core:1.9.5"
52+
testCompile 'junit:junit:4.12'
53+
testCompile 'org.mockito:mockito-core:1.9.5'
54+
testCompile 'org.robolectric:robolectric:3.0-SNAPSHOT'
5055
}
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package com.anbroidsdev.converter;
2+
3+
import android.annotation.TargetApi;
4+
import android.content.SharedPreferences;
5+
import android.os.Build;
6+
7+
import com.google.gson.Gson;
8+
import com.google.gson.JsonSyntaxException;
9+
10+
import java.lang.reflect.Type;
11+
import java.util.Map;
12+
import java.util.Set;
13+
14+
public class ObjectSharedPreferences implements SharedPreferences {
15+
16+
private final SharedPreferences delegate;
17+
private final Editor editor;
18+
private final Gson gson;
19+
20+
public ObjectSharedPreferences(SharedPreferences delegate) {
21+
this.delegate = delegate;
22+
this.editor = new Editor();
23+
this.gson = new Gson();
24+
}
25+
26+
public class Editor implements SharedPreferences.Editor {
27+
28+
protected SharedPreferences.Editor delegate;
29+
30+
public Editor() {
31+
this.delegate = ObjectSharedPreferences.this.delegate.edit();
32+
}
33+
34+
@Override
35+
public Editor putBoolean(String key, boolean value) {
36+
delegate.putBoolean(key, value);
37+
38+
return this;
39+
}
40+
41+
@Override
42+
public Editor putFloat(String key, float value) {
43+
delegate.putFloat(key, value);
44+
45+
return this;
46+
}
47+
48+
@Override
49+
public Editor putInt(String key, int value) {
50+
delegate.putInt(key, value);
51+
52+
return this;
53+
}
54+
55+
@Override
56+
public Editor putLong(String key, long value) {
57+
delegate.putLong(key, value);
58+
59+
return this;
60+
}
61+
62+
@Override
63+
public Editor putString(String key, String value) {
64+
delegate.putString(key, value);
65+
66+
return this;
67+
}
68+
69+
@Override
70+
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
71+
public Editor putStringSet(String key, Set<String> values) {
72+
delegate.putStringSet(key, values);
73+
74+
return this;
75+
}
76+
77+
public <T> SharedPreferences.Editor putObject(String key, T object) {
78+
delegate.putString(key, object != null ? gson.toJson(object) : null);
79+
80+
return this;
81+
}
82+
83+
@Override
84+
public void apply() {
85+
delegate.apply();
86+
}
87+
88+
@Override
89+
public Editor clear() {
90+
delegate.clear();
91+
92+
return this;
93+
}
94+
95+
@Deprecated
96+
/**
97+
*
98+
* @deprecated use {@link apply()} instead.
99+
*/
100+
public boolean commit() {
101+
delegate.apply();
102+
103+
return true;
104+
}
105+
106+
@Override
107+
public Editor remove(String s) {
108+
delegate.remove(s);
109+
110+
return this;
111+
}
112+
}
113+
114+
public Editor edit() {
115+
return editor;
116+
}
117+
118+
@Override
119+
public Map<String, ?> getAll() {
120+
return delegate.getAll();
121+
}
122+
123+
@Override
124+
public boolean getBoolean(String key, boolean defValue) {
125+
return delegate.getBoolean(key, defValue);
126+
}
127+
128+
@Override
129+
public float getFloat(String key, float defValue) {
130+
return delegate.getFloat(key, defValue);
131+
}
132+
133+
@Override
134+
public int getInt(String key, int defValue) {
135+
return delegate.getInt(key, defValue);
136+
}
137+
138+
@Override
139+
public long getLong(String key, long defValue) {
140+
return delegate.getLong(key, defValue);
141+
}
142+
143+
@Override
144+
public String getString(String key, String defValue) {
145+
return delegate.getString(key, defValue);
146+
}
147+
148+
@Override
149+
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
150+
public Set<String> getStringSet(String key, Set<String> defValues) {
151+
return delegate.getStringSet(key, defValues);
152+
}
153+
154+
public <T> T getObject(String key, Class<T> theClass) {
155+
try {
156+
return gson.fromJson(delegate.getString(key, null), theClass);
157+
} catch (JsonSyntaxException e) {
158+
editor.remove(key);
159+
editor.apply();
160+
161+
return null;
162+
}
163+
}
164+
165+
public <T> T getObject(String key, Type typeOf) {
166+
try {
167+
return gson.fromJson(delegate.getString(key, null), typeOf);
168+
} catch (JsonSyntaxException e) {
169+
editor.remove(key);
170+
editor.apply();
171+
172+
return null;
173+
}
174+
}
175+
176+
@Override
177+
public boolean contains(String s) {
178+
return delegate.contains(s);
179+
}
180+
181+
@Override
182+
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {
183+
delegate.registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);
184+
}
185+
186+
@Override
187+
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {
188+
delegate.unregisterOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);
189+
}
190+
191+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.anbroidsdev.converter;
2+
3+
import java.util.Currency;
4+
import java.util.Map;
5+
6+
public interface RatesSaver {
7+
8+
public void saveRates(Map<Currency, Double> rates, long timestamp);
9+
public Map<Currency, Double> getLastSavedRates();
10+
public long getLastSavedRatesTimestamp();
11+
12+
}

app/src/main/java/com/anbroidsdev/converter/MoneyConverterRatesUpdater.java renamed to app/src/main/java/com/anbroidsdev/converter/RatesUpdater.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,39 @@
11
package com.anbroidsdev.converter;
22

33
import java.util.Currency;
4-
import java.util.HashMap;
54
import java.util.Map;
65

7-
public class MoneyConverterRatesUpdater {
6+
public class RatesUpdater {
87

98
public interface OnRatesUpdateListener {
109

11-
public void onRatesUpdated(Map<Currency, Double> rates, long timestamp);
10+
public void onRatesUpdated();
1211

1312
}
1413

1514
private final MoneyConverter moneyConverter;
1615
private final OpenExchangeRatesApi openExchangeRatesApi;
16+
private final RatesSaver ratesSaver;
1717

18-
public MoneyConverterRatesUpdater(MoneyConverter moneyConverter, OpenExchangeRatesApi openExchangeRatesApi) {
18+
public RatesUpdater(MoneyConverter moneyConverter, OpenExchangeRatesApi openExchangeRatesApi, RatesSaver ratesSaver) {
1919
this.moneyConverter = moneyConverter;
2020
this.openExchangeRatesApi = openExchangeRatesApi;
21+
this.ratesSaver = ratesSaver;
2122
}
2223

2324
public void updateRates(final OnRatesUpdateListener listener) {
2425
openExchangeRatesApi.getLatestRates(moneyConverter.getBase().getCurrencyCode(), new OpenExchangeRatesApi.OnLatestRatesCallback() {
2526

2627
@Override
2728
public void onLatestRates(Map<String, Double> rates, long timestamp) {
28-
final Map<Currency, Double> newRates = new HashMap<>(rates.size());
29+
final Map<Currency, Double> newRates = RatesUtils.ratesAsCurrencies(rates);
2930

30-
for (Map.Entry<String, Double> rate : rates.entrySet()) {
31-
try {
32-
newRates.put(Currency.getInstance(rate.getKey()), rate.getValue());
33-
} catch (IllegalArgumentException e) {}
34-
}
31+
ratesSaver.saveRates(newRates, timestamp);
3532

3633
moneyConverter.setRates(newRates);
3734

3835
if (listener != null) {
39-
listener.onRatesUpdated(newRates, timestamp);
36+
listener.onRatesUpdated();
4037
}
4138
}
4239

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.anbroidsdev.converter;
2+
3+
import java.util.Currency;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
public class RatesUtils {
8+
9+
public static Map<String, Double> ratesAsStrings(Map<Currency, Double> rates) {
10+
if (rates == null) {
11+
return null;
12+
}
13+
14+
final Map<String, Double> newRates = new HashMap<>(rates.size());
15+
16+
for (Map.Entry<Currency, Double> rate : rates.entrySet()) {
17+
newRates.put(rate.getKey().getCurrencyCode(), rate.getValue());
18+
}
19+
20+
return newRates;
21+
}
22+
23+
public static Map<Currency, Double> ratesAsCurrencies(Map<String, Double> rates) {
24+
if (rates == null) {
25+
return null;
26+
}
27+
28+
final Map<Currency, Double> newRates = new HashMap<>(rates.size());
29+
30+
for (Map.Entry<String, Double> rate : rates.entrySet()) {
31+
try {
32+
newRates.put(Currency.getInstance(rate.getKey()), rate.getValue());
33+
} catch (IllegalArgumentException e) {}
34+
}
35+
36+
return newRates;
37+
}
38+
39+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.anbroidsdev.converter;
2+
3+
import android.content.Context;
4+
5+
import com.google.gson.reflect.TypeToken;
6+
7+
import java.lang.reflect.Type;
8+
import java.util.Currency;
9+
import java.util.Map;
10+
11+
public class SharedPreferencesRatesSaver implements RatesSaver {
12+
13+
private static final String RATES = "rates";
14+
private static final String TIMESTAMP = "timestamp";
15+
16+
private static final Type TYPE = new TypeToken<Map<String, Double>>(){}.getType();
17+
18+
private final ObjectSharedPreferences.Editor sharedPreferencesEditor;
19+
20+
private Map<Currency, Double> lastSavedRates;
21+
private long lastSavedRatesTimestamp;
22+
23+
public SharedPreferencesRatesSaver(Context context) {
24+
final ObjectSharedPreferences sharedPreferences = new ObjectSharedPreferences(context.getSharedPreferences("rates", Context.MODE_PRIVATE));
25+
this.sharedPreferencesEditor = sharedPreferences.edit();
26+
27+
lastSavedRates = RatesUtils.ratesAsCurrencies(sharedPreferences.<Map<String, Double>>getObject(RATES, TYPE));
28+
lastSavedRatesTimestamp = sharedPreferences.getLong(TIMESTAMP, 0);
29+
}
30+
31+
public void saveRates(Map<Currency, Double> rates, long timestamp) {
32+
lastSavedRates = rates;
33+
lastSavedRatesTimestamp = timestamp;
34+
35+
sharedPreferencesEditor.putObject(RATES, RatesUtils.ratesAsStrings(rates));
36+
sharedPreferencesEditor.putLong(TIMESTAMP, timestamp);
37+
sharedPreferencesEditor.apply();
38+
}
39+
40+
public Map<Currency, Double> getLastSavedRates() {
41+
return lastSavedRates;
42+
}
43+
44+
public long getLastSavedRatesTimestamp() {
45+
return lastSavedRatesTimestamp;
46+
}
47+
48+
public void clear() {
49+
sharedPreferencesEditor.remove(RATES);
50+
sharedPreferencesEditor.remove(TIMESTAMP);
51+
sharedPreferencesEditor.apply();
52+
}
53+
54+
}

0 commit comments

Comments
 (0)