Releases: RedMadRobot/mapmemory
v2.1
Reusable properties
Reusable properties introduced to address the problem described in issue #14
Reusable properties survive MapMemory.clear()
call. It will not be removed from cache, but will be cleared instead. Reusable properties are especially useful for reactive types like Flow
. You don't need to resubscribe to flow after MapMemory was cleared.
val flow by memory.sharedFlow<Int>()
// Subscribe to flow
flow.onEach(::println).launchIn(coroutineScope)
// And then clear MapMemory
memory.crear()
// Emitted value will be printed because the flow
// is the same as before memory clear
flow.emit(1)
You can create reusable property using operator invoke
with clear
lambda:
class Counter {
fun reset() = { /*...*/ }
}
val counter: Counter by memory(clear = { it.reset() }) { Counter() }
Many of default accessors are already turned into reusable: mutableList
, mutableMap
, reactiveMutableMap
, stateFlow
, sharedFlow
, behaviorSubject
, publishSubject
.
Changes
⚠️ Deprecated functions removed:MapMemory.nullable
,MapMemory.reactiveMap
,ReactiveMutableMap.getStream
,ReactiveMutableMap.getAll
,ReactiveMutableMap.getAllStream
- Added parameter
defaultValue
to most of reusable properties:mutableList
,mutableMap
,reactiveMutableMap
,behaviorSubject
. ⚠️ mapmemory-rxjava:ReplayStrategy
was removed. Please let us know if this change affected you: #20
Fixes
- ReactiveMutableMap: initial empty map is not emitted (#15)
Dependencies
- mapmemory: Kotlin
1.4.30
→1.8.20
- mapmemory-coroutines: kotlinx.coroutines
1.4.2
→1.6.4
- mapmemory-rxjava3: RxJava
3.0.11
→3.1.6
Housekeeping
- infrastructure
0.8.2
→0.18.1
- detekt
1.16.0
→1.22.0
- Gradle
6.8.3
→8.1.1
- binary-compatibility-validator
0.5.0
→0.13.1
Full Changelog: v2.0...v2.1
v2.0
ReactiveMap refactored
ReactiveMap
renamed to ReactiveMutableMap
.
There are two type parameters K
(for keys), V
(for values) instead of one T
(for values), so you can use keys with a type different from String
.
Now ReactiveMutableMap
implements interface MutableMap
.
Also, you can wrap Map
with ReactiveMutableMap
, using constructor.
Naming changes
Old versions of methods are marked with
@Deprecated
to help migrate to new naming.
Methods getAll
replaced with field values
to match Map
interface.
Word stream
in methods names replaced with implementation-specific words to make API clearer.
Coroutines:
getStream
→getFlow
andgetValueFlow
getAllStream
→valuesFlow
- New field
flow
with the whole map
RxJava:
getStream
→getValueObservable
getAllStream
→valuesObservable
- New field
observable
with the whole map
KAPT: 'IllegalStateException: Couldn't find declaration file' on delegate with inline getValue operator
There is a bug in Kotlin Compiler that affects MapMemory if you create subclasses - KT-46317.
You can use module mapmemory-kapt-bug-workaround
as a workaround:
dependencies {
implementation("com.redmadrobot.mapmemory:mapmemory-kapt-bug-workaround:[latest-version]")
}
- val someValue: String by memory
+ val someValue: String by memory.value()
v2.0-rc1
Scoped and shared values (#1)
Now there are two types of memory values: scoped (to class) and shared.
All memory values by default are scoped to the class where it's declared.
Scoping prevents from unintended sharing of properties with the same name between classes.
This snippet demonstrates the problem:
package com.example
class StringsStorage(memory: MapMemory) {
var values: MutableList<String> by memory.list()
}
class IntsStorage(memory: MapMemory) {
var values: MutableList<Int> by memory.list() // The same field name as in StringsStorage
}
val strings = StringsStorage(memory)
val ints = IntsStorage(memory)
strings.values.add("A")
ints.values.add(1)
println(memory)
Output:
For unscoped fields (old behaviour):
{values: [A, 1]}
For scoped fields (new behavior):
{com.example.StringsStorage#values: [A], com.example.IntsStorage#values: [1]}
You can make memory field shared using extension shared(key: String)
:
// It is recommended to create constants for shared properties keys
const val KEY_SERVER_HOST = "serverHost"
class ServerConfig(memory: MapMemory) {
var host: String by memory.shared(KEY_SERVER_HOST)
}
class DebugPanelConfig(memory: MapMemory) {
var serverHost: String by memory.shared(KEY_SERVER_HOST)
}
Removed .nullable()
and .withDefault { ... }
Accessor nullable()
is not needed now.
You can just declare a nullable field:
-val selectedOption: String? by memory.nullable()
+val selectedOption: String? by memory
withDefault
is no more compatible with MapMemory, so you should use the operator invoke
instead:
-var counter: Int by memory.withDefault { 0 }
+var counter: Int by memory { 0 }
Mutable collections accessors
BREAKING CHANGE
Now accessors map
and list
return delegates to access immutable collections.
You should use mutableMap
and mutableList
for mutable versions of collections.
Added
- Copying constructor for
MapMemory
.
Now you can initialize memory with specified content on creation. - New module
mapmemory-test
.
Contains utilities helping to test code that usesMapMemory
. - New module
mapmemory-rxjava3
with accessors for RxJava3.
Changed
MapMemory
now isMutableMap<String, Any>
instead ofMutableMap<String, Any?>
.
It is made to prevent NPEs becauseConcurrentHashMap
not supports nullable values.
You still can store nullable values in memory using a delegate.