Last active
March 4, 2017 17:42
-
-
Save vganin/cf36838e15d0576fb66a278f88a86f87 to your computer and use it in GitHub Desktop.
Kotlin FragmentArgs
This file contains hidden or 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
import android.app.Fragment | |
import android.os.Bundle | |
import kotlin.properties.ReadWriteProperty | |
import kotlin.reflect.KProperty | |
import android.support.v4.app.Fragment as SupportFragment | |
inline fun <reified T> Fragment.fragmentArg() | |
: ReadWriteProperty<Fragment, T> = required({ argumentsRequired }) | |
inline fun <reified T> SupportFragment.fragmentArg() | |
: ReadWriteProperty<SupportFragment, T> = required({ argumentsRequired }) | |
inline fun <reified T> Fragment.fragmentArgOptional() | |
: ReadWriteProperty<Fragment, T?> = optional({ argumentsRequired }) | |
inline fun <reified T> SupportFragment.fragmentArgOptional() | |
: ReadWriteProperty<SupportFragment, T?> = optional({ argumentsRequired }) | |
val Fragment.argumentsRequired: Bundle | |
get() { | |
if (arguments == null) arguments = Bundle() | |
return arguments | |
} | |
val SupportFragment.argumentsRequired: Bundle | |
get() { | |
if (arguments == null) arguments = Bundle() | |
return arguments | |
} | |
inline fun <reified T> Bundle.putArg(key: String, value: T): Unit { | |
when (value) { | |
is Int -> putInt(key, value) | |
is Long -> putLong(key, value) | |
is String -> getString(key, value) | |
// TODO: More | |
else -> throw IllegalStateException("Cannot put type ${T::class.java.name} into Bundle") | |
} | |
} | |
inline fun <reified T> Bundle.getArg(key: String): T? { | |
return when (T::class) { | |
Int::class -> getInt(key) as T? | |
Long::class -> getLong(key) as T? | |
String::class -> getString(key) as T? | |
// TODO: More | |
else -> throw IllegalStateException("Cannot get type ${T::class.java.name} from Bundle") | |
} | |
} | |
inline fun <reified T> required(crossinline bundleSupplier: () -> Bundle) = ReadWriteFragmentArg( | |
{ prop, value: T -> bundleSupplier().putArg(prop.name, value) }, | |
{ prop -> bundleSupplier().getArg<T>(prop.name) ?: requiredFailed(prop) } | |
) | |
inline fun <reified T> optional(crossinline bundleSupplier: () -> Bundle) = ReadWriteFragmentArg( | |
{ prop, value: T? -> bundleSupplier().putArg(prop.name, value) }, | |
{ prop -> bundleSupplier().getArg<T?>(prop.name) } | |
) | |
fun requiredFailed(desc: KProperty<*>): Nothing = | |
throw IllegalStateException("Required argument for property '${desc.name}' not found") | |
class ReadWriteFragmentArg<T> ( | |
private val argSetter: (KProperty<*>, T) -> Unit, | |
private val argGetter: (KProperty<*>) -> T | |
) : ReadWriteProperty<Any, T> { | |
private object EMPTY | |
private var _value: Any? = EMPTY | |
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) { | |
argSetter(property, value) | |
} | |
override fun getValue(thisRef: Any, property: KProperty<*>): T { | |
if (_value == EMPTY) { | |
_value = argGetter(property) | |
} | |
@Suppress("UNCHECKED_CAST") | |
return _value as T | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment