Last active
October 6, 2017 17:35
-
-
Save AAverin/c65d2c485be0f4c3ecdaa2ef049aebfe to your computer and use it in GitHub Desktop.
A simple consistency manager implementation on Kotlin. You can subscribe on some class changes, and notify subscribers about that class being updated. Convinient when you have data being displayed in many different places and you need it up to date any time it changes, eg. somebody is making item favorite and 'star' icons should update everywhere
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface ConsistencyManagerContract { | |
fun notifyUpdateModel(model: Any) | |
fun notifyUpdateClass(kclass: KClass<*>) | |
fun subscribe(modelClass: KClass<*>, callback: WeakReference<(Any?) -> Unit>) | |
} | |
class ConsistencyManager : ConsistencyManagerContract { | |
private val subscriptionsMap: MutableMap<KClass<*>, MutableList<WeakReference<(Any?) -> Unit>>> = mutableMapOf() | |
override fun notifyUpdateModel(model: Any) { | |
val kotlinClass = model.javaClass.kotlin | |
subscriptionsMap[kotlinClass]?.forEach { | |
it.get()?.invoke(model) | |
} | |
} | |
override fun notifyUpdateClass(kclass: KClass<*>) { | |
subscriptionsMap[kclass]?.forEach { | |
it.get()?.invoke(null) | |
} | |
} | |
override fun subscribe(modelClass: KClass<*>, callback: WeakReference<(Any?) -> Unit>) { | |
var subscriptionsForModel = subscriptionsMap[modelClass] | |
if (subscriptionsForModel == null) { | |
subscriptionsForModel = mutableListOf(callback) | |
subscriptionsMap.put(modelClass, subscriptionsForModel) | |
} else { | |
if (subscriptionsForModel.firstOrNull() { it.get() == callback.get() } == null) { | |
subscriptionsForModel.add(callback) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@RunWith(PowerMockRunner::class) | |
@PrepareForTest() | |
class ConsistencyManagerTest { | |
private val classToTest = ConsistencyManager() | |
private val model = Article::class | |
private var testCallback1Called = 0 | |
private var testCallback2Called = 0 | |
private val testCallback1: (Any?) -> Unit = { a -> | |
testCallback1Called++ | |
} | |
private val testCallback2: (Any?) -> Unit = { a -> | |
testCallback2Called++ | |
} | |
@Test | |
fun subscribesModel() { | |
// given | |
classToTest.subscribe(model, WeakReference(testCallback1)) | |
// when | |
classToTest.notifyUpdateModel(Article()) | |
// then | |
assertThat(testCallback1Called, isEqualTo(1)) | |
} | |
@Test | |
fun subscribesModelOnlyOnce() { | |
// given | |
classToTest.subscribe(model, WeakReference(testCallback1)) | |
classToTest.subscribe(model, WeakReference(testCallback1)) | |
classToTest.subscribe(model, WeakReference(testCallback1)) | |
// when | |
classToTest.notifyUpdateModel(Article()) | |
// then | |
assertThat(testCallback1Called, isEqualTo(1)) | |
} | |
@Test | |
fun subscribesMultipleCallbacks() { | |
// given | |
classToTest.subscribe(model, WeakReference(testCallback1)) | |
classToTest.subscribe(model, WeakReference(testCallback2)) | |
// when | |
classToTest.notifyUpdateModel(Article()) | |
// then | |
assertThat(testCallback1Called, isEqualTo(1)) | |
assertThat(testCallback2Called, isEqualTo(1)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment