Skip to content

Commit 408f639

Browse files
authored
Merge pull request #24 from launchdarkly/dr/2.0.3
Improve thread safety when unregistering listeners
2 parents 035d866 + 7a7aada commit 408f639

File tree

6 files changed

+30
-16
lines changed

6 files changed

+30
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
All notable changes to the LaunchDarkly Android SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org).
55

6+
## [2.0.3] - 2017-05-18
7+
### Changed
8+
- Even better thread safety in UserManager when removing change listeners.
9+
610
## [2.0.2] - 2017-05-03
711
### Changed
812
- Improved thread safety in UserManager when removing change listeners.

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ buildscript {
55
jcenter()
66
}
77
dependencies {
8-
classpath 'com.android.tools.build:gradle:2.3.1'
8+
classpath 'com.android.tools.build:gradle:2.3.2'
99

1010
// For displaying method/field counts when building with Gradle:
1111
// https://github.com/KeepSafe/dexcount-gradle-plugin

circle.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@ dependencies:
99
# Android SDK Platform 24
1010
- if [ ! -d "/usr/local/android-sdk-linux/platforms/android-24" ]; then echo y | android update sdk --no-ui --all --filter "android-24"; fi
1111
# Android SDK Build-tools
12-
- if [ ! -d "/usr/local/android-sdk-linux/build-tools/25.0.2" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-25.0.2"; fi
12+
- if [ ! -d "/usr/local/android-sdk-linux/build-tools/25.0.2" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-25.0.3"; fi
1313
# brings in appcompat
1414
- if [ ! -d "/usr/local/android-sdk-linux/extras/android/m2repository" ]; then echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"; fi
15+
- mkdir -p /usr/local/android-sdk-linux/licenses
16+
- aws s3 cp s3://launchdarkly-pastebin/ci/android/licenses/android-sdk-license /usr/local/android-sdk-linux/licenses/android-sdk-license
17+
- aws s3 cp s3://launchdarkly-pastebin/ci/android/licenses/intel-android-extra-license /usr/local/android-sdk-linux/licenses/intel-android-extra-license
1518
cache_directories:
1619
- /usr/local/android-sdk-linux/platforms/android-24
17-
- /usr/local/android-sdk-linux/build-tools/25.0.2
20+
- /usr/local/android-sdk-linux/build-tools/25.0.3
1821
- /usr/local/android-sdk-linux/extras/android/m2repository
1922
test:
2023
override:
24+
- unset ANDROID_NDK_HOME
2125
- emulator -avd circleci-android24 -no-audio -no-window:
2226
background: true
2327
parallel: true

example/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repositories {
1111

1212
android {
1313
compileSdkVersion 24
14-
buildToolsVersion '25.0.2'
14+
buildToolsVersion '25.0.3'
1515
defaultConfig {
1616
applicationId "com.launchdarkly.example"
1717
minSdkVersion 15

launchdarkly-android-client/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ apply plugin: 'com.getkeepsafe.dexcount'
77

88
allprojects {
99
group = 'com.launchdarkly'
10-
version = '2.0.2'
10+
version = '2.0.3'
1111
sourceCompatibility = 1.7
1212
targetCompatibility = 1.7
1313
}
1414

1515
android {
1616
compileSdkVersion 24
17-
buildToolsVersion '25.0.2'
17+
buildToolsVersion '25.0.3'
1818

1919
defaultConfig {
2020
minSdkVersion 15

launchdarkly-android-client/src/main/java/com/launchdarkly/android/UserManager.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ class UserManager {
5151

5252
private final Application application;
5353
// Maintains references enabling (de)registration of listeners for realtime updates
54-
private final Multimap<String, Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener>> listeners =
55-
Multimaps.synchronizedMultimap(ArrayListMultimap.<String, Pair<FeatureFlagChangeListener,OnSharedPreferenceChangeListener>>create());
54+
private final Multimap<String, Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener>> listeners = ArrayListMultimap.create();
5655

5756
// The current user- we'll always fetch this user from the response we get from the api
5857
private SharedPreferences currentUserSharedPrefs;
@@ -116,6 +115,7 @@ void setCurrentUser(final LDUser user) {
116115

117116
/**
118117
* Completely deletes a user's saved flag settings and the remaining empty SharedPreferences xml file.
118+
*
119119
* @param userKey
120120
*/
121121
private void deleteSharedPreferences(String userKey) {
@@ -166,17 +166,21 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
166166
}
167167
}
168168
};
169-
listeners.put(key, new Pair<>(listener, sharedPrefsListener));
169+
synchronized (listeners) {
170+
listeners.put(key, new Pair<>(listener, sharedPrefsListener));
171+
}
170172
activeUserSharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefsListener);
171173
Log.d(TAG, "Added listener. Total count: [" + listeners.size() + "]");
172174
}
173175

174176
void unregisterListener(String key, FeatureFlagChangeListener listener) {
175-
for (Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener> pair : listeners.get(key)) {
176-
if (pair.first.equals(listener)) {
177-
Log.d(TAG, "Removing listener for key: [" + key + "]");
178-
activeUserSharedPrefs.unregisterOnSharedPreferenceChangeListener(pair.second);
179-
listeners.remove(key, pair);
177+
synchronized (listeners) {
178+
for (Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener> pair : listeners.get(key)) {
179+
if (pair.first.equals(listener)) {
180+
Log.d(TAG, "Removing listener for key: [" + key + "]");
181+
activeUserSharedPrefs.unregisterOnSharedPreferenceChangeListener(pair.second);
182+
listeners.remove(key, pair);
183+
}
180184
}
181185
}
182186
}
@@ -190,7 +194,7 @@ void unregisterListener(String key, FeatureFlagChangeListener listener) {
190194
* @param flags
191195
*/
192196
private void saveFlagSettings(JsonObject flags) {
193-
Log.d(TAG, "saveFlagSettings for user key: "+ currentUser.getKey());
197+
Log.d(TAG, "saveFlagSettings for user key: " + currentUser.getKey());
194198
SharedPreferences.Editor currentEditor = currentUserSharedPrefs.edit();
195199
currentEditor.clear();
196200

@@ -260,7 +264,9 @@ private void syncCurrentUserToActiveUser() {
260264
if (current.get(key) == null) {
261265
Log.d(tag, "Deleting value and listeners for key: [" + key + "]");
262266
activeEditor.remove(key);
263-
listeners.removeAll(key);
267+
synchronized (listeners) {
268+
listeners.removeAll(key);
269+
}
264270
}
265271
}
266272
activeEditor.apply();

0 commit comments

Comments
 (0)