Save state with Delegates

class SampleFragment : Fragment() {

private var desiredString: String = ""
private var location
: Location? = null

override fun
onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
savedInstanceState?.run {
desiredString
= getString(DESIRED_KEY) ?: ""
location = get(LOCATION_KEY) as? Location
}
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString(DESIRED_KEY, desiredString)
outState.putParcelable(LOCATION_KEY, location)
}

companion object {
private const val DESIRED_KEY = "DESIRED_KEY"
private const val LOCATION_KEY
= "LOCATION_KEY"
}
}

Solution

open class BaseFragment : Fragment() {    private val savable = Bundle()override fun onCreate(savedInstanceState: Bundle?) {
if(savedInstanceState != null) {
savable.putAll(savedInstanceState.getBundle("_state"))
}
super.onCreate(savedInstanceState)
}

override fun onSaveInstanceState(outState: Bundle) {
outState.putBundle("_state", savable)
super.onSaveInstanceState(outState)
}


protected fun <T> instanceState() = InstanceStateProvider.Nullable<T>(savable)
protected fun <T> instanceState(defaultValue: T) = InstanceStateProvider.NotNull(savable, defaultValue)
}
class SampleFragment : BaseFragment() {
private var desiredString: String by instanceState("")
private var location: Location? by instanceState()

//...some code
}
open class InstanceStateProvider<T>(private val savable: Bundle) {

private var cache: T? = null

operator fun
setValue(thisRef: Any?, property: KProperty<*>, value: T) {
cache = value
if (value == null) {
savable.remove(property.name)
return
}
when (value) {
is Int -> savable.putInt(property.name, value)
is Long -> savable.putLong(property.name, value)
is Float -> savable.putFloat(property.name, value)
is String -> savable.putString(property.name, value)
is Bundle -> savable.putBundle(property.name, value)
is Serializable -> savable.putSerializable(property.name, value)
is Parcelable -> savable.putParcelable(property.name, value)
}
}

protected fun getAndCache(key: String): T? = cache ?: (savable.get(key) as T?).apply { cache = this }

class
Nullable<T>(savable: Bundle) : InstanceStateProvider<T>(savable) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? = getAndCache(property.name)
}

class NotNull<T>(savable: Bundle, private val defaultValue: T) : InstanceStateProvider<T>(savable) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = getAndCache(property.name) ?: defaultValue
}
}

Afterwords

--

--

--

Love being creative to solve some problems with an simple and elegant ways

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Java, reference variable

You can still save your Magento Store’s Life - Here is HOW? :)

Every Second Counts:Pure SaaS based performance testing platform to Increase business

Five Things Every Starting Scrum Master Should Know

Participating Google Code Jam(the First Time)

State of Android Keyboard in the year 2020

Text Mining: Named Entity Recognition, Parts of Speech and Sentence Structures

Configuring your GPU Server for the AI Racing League

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Michael Spitsin

Michael Spitsin

Love being creative to solve some problems with an simple and elegant ways

More from Medium

Using Huawei App Messaging in Android

Android Dagger with a MultiModule structure

Using Android Content Providers for Automatically Initialization

Room Database Migration in Kotlin