Skip to content

Commit

Permalink
Merge pull request #24 from launchdarkly/dr/2.0.3
Browse files Browse the repository at this point in the history
Improve thread safety when unregistering listeners
  • Loading branch information
drichelson authored May 18, 2017
2 parents 035d866 + 7a7aada commit 408f639
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

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

## [2.0.3] - 2017-05-18
### Changed
- Even better thread safety in UserManager when removing change listeners.

## [2.0.2] - 2017-05-03
### Changed
- Improved thread safety in UserManager when removing change listeners.
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'com.android.tools.build:gradle:2.3.2'

// For displaying method/field counts when building with Gradle:
// https://github.com/KeepSafe/dexcount-gradle-plugin
Expand Down
8 changes: 6 additions & 2 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ dependencies:
# Android SDK Platform 24
- if [ ! -d "/usr/local/android-sdk-linux/platforms/android-24" ]; then echo y | android update sdk --no-ui --all --filter "android-24"; fi
# Android SDK Build-tools
- 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
- 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
# brings in appcompat
- if [ ! -d "/usr/local/android-sdk-linux/extras/android/m2repository" ]; then echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"; fi
- mkdir -p /usr/local/android-sdk-linux/licenses
- aws s3 cp s3://launchdarkly-pastebin/ci/android/licenses/android-sdk-license /usr/local/android-sdk-linux/licenses/android-sdk-license
- aws s3 cp s3://launchdarkly-pastebin/ci/android/licenses/intel-android-extra-license /usr/local/android-sdk-linux/licenses/intel-android-extra-license
cache_directories:
- /usr/local/android-sdk-linux/platforms/android-24
- /usr/local/android-sdk-linux/build-tools/25.0.2
- /usr/local/android-sdk-linux/build-tools/25.0.3
- /usr/local/android-sdk-linux/extras/android/m2repository
test:
override:
- unset ANDROID_NDK_HOME
- emulator -avd circleci-android24 -no-audio -no-window:
background: true
parallel: true
Expand Down
2 changes: 1 addition & 1 deletion example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repositories {

android {
compileSdkVersion 24
buildToolsVersion '25.0.2'
buildToolsVersion '25.0.3'
defaultConfig {
applicationId "com.launchdarkly.example"
minSdkVersion 15
Expand Down
4 changes: 2 additions & 2 deletions launchdarkly-android-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ apply plugin: 'com.getkeepsafe.dexcount'

allprojects {
group = 'com.launchdarkly'
version = '2.0.2'
version = '2.0.3'
sourceCompatibility = 1.7
targetCompatibility = 1.7
}

android {
compileSdkVersion 24
buildToolsVersion '25.0.2'
buildToolsVersion '25.0.3'

defaultConfig {
minSdkVersion 15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ class UserManager {

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

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

/**
* Completely deletes a user's saved flag settings and the remaining empty SharedPreferences xml file.
*
* @param userKey
*/
private void deleteSharedPreferences(String userKey) {
Expand Down Expand Up @@ -166,17 +166,21 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
}
}
};
listeners.put(key, new Pair<>(listener, sharedPrefsListener));
synchronized (listeners) {
listeners.put(key, new Pair<>(listener, sharedPrefsListener));
}
activeUserSharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefsListener);
Log.d(TAG, "Added listener. Total count: [" + listeners.size() + "]");
}

void unregisterListener(String key, FeatureFlagChangeListener listener) {
for (Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener> pair : listeners.get(key)) {
if (pair.first.equals(listener)) {
Log.d(TAG, "Removing listener for key: [" + key + "]");
activeUserSharedPrefs.unregisterOnSharedPreferenceChangeListener(pair.second);
listeners.remove(key, pair);
synchronized (listeners) {
for (Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener> pair : listeners.get(key)) {
if (pair.first.equals(listener)) {
Log.d(TAG, "Removing listener for key: [" + key + "]");
activeUserSharedPrefs.unregisterOnSharedPreferenceChangeListener(pair.second);
listeners.remove(key, pair);
}
}
}
}
Expand All @@ -190,7 +194,7 @@ void unregisterListener(String key, FeatureFlagChangeListener listener) {
* @param flags
*/
private void saveFlagSettings(JsonObject flags) {
Log.d(TAG, "saveFlagSettings for user key: "+ currentUser.getKey());
Log.d(TAG, "saveFlagSettings for user key: " + currentUser.getKey());
SharedPreferences.Editor currentEditor = currentUserSharedPrefs.edit();
currentEditor.clear();

Expand Down Expand Up @@ -260,7 +264,9 @@ private void syncCurrentUserToActiveUser() {
if (current.get(key) == null) {
Log.d(tag, "Deleting value and listeners for key: [" + key + "]");
activeEditor.remove(key);
listeners.removeAll(key);
synchronized (listeners) {
listeners.removeAll(key);
}
}
}
activeEditor.apply();
Expand Down

0 comments on commit 408f639

Please sign in to comment.