Created
April 8, 2017 09:50
-
-
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
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
/** | |
* Created with Android Studio | |
* User: electrolobzik [email protected] | |
* 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