Skip to content

Instantly share code, notes, and snippets.

@electrolobzik
Created April 8, 2017 09:50
Show Gist options
  • Save electrolobzik/d481a11a4053ebeb38ea79c15cea5c9e to your computer and use it in GitHub Desktop.
Save electrolobzik/d481a11a4053ebeb38ea79c15cea5c9e to your computer and use it in GitHub Desktop.
Provides delegates for implementing regular and lazy not nullable properties which should be disposed in some moment to free memory
/**
* Created with Android Studio
* User: electrolobzik electrolobzik@gmail.com
* Date: 07/04/2017
* Time: 18:55
*
* Provides delegates for implementing regular and lazy not nullable properties which should be disposed in some moment to free memory
*/
class DisposablePropertyManager {
private val propertyDelegates: ArrayList<Disposable> = ArrayList()
fun <T : Any> disposableLazy(initializer: () -> T): ReadOnlyProperty<Any?, T> {
return SynchronizedLazyDisposableImpl(initializer).apply { propertyDelegates.add(this) }
}
fun <T : Any> disposable(): ReadWriteProperty<Any?, T> {
return RegularDisposableImpl<T>().apply { propertyDelegates.add(this) }
}
fun dispose() {
for (delegate in propertyDelegates) {
delegate.dispose()
}
}
fun restore() {
for (delegate in propertyDelegates) {
delegate.restore()
}
}
}
private interface Disposable {
fun dispose()
fun restore()
}
private class RegularDisposableImpl<T: Any> : ReadWriteProperty<Any?, T>, Disposable {
private var value: T? = null
private var disposed: Boolean = false
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (disposed) {
throw IllegalStateException("Property ${property.name} has been disposed and should be restored before get.")
}
return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.")
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}
override fun dispose() {
disposed = true
value = null
}
override fun restore() {
disposed = false
}
}
private class SynchronizedLazyDisposableImpl<out T>(initializer: () -> T, lock: Any? = null) : ReadOnlyProperty<Any?, T>, Disposable {
@Volatile private var value: Any? = UNINITIALIZED_VALUE
private var disposed: Boolean = false
private var initializer: (() -> T) = initializer
private val lock = lock ?: this
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (disposed) {
throw IllegalStateException("Property ${property.name} has been disposed and should be restored before get.")
}
val _v1 = value
if (_v1 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return _v1 as T
}
return synchronized(lock) {
val _v2 = value
if (_v2 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST") (_v2 as T)
}
else {
val typedValue = initializer()
value = typedValue
typedValue
}
}
}
override fun dispose() {
disposed = true
value = UNINITIALIZED_VALUE
}
override fun restore() {
disposed = false
}
}
private object UNINITIALIZED_VALUE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment