Skip to content

Instantly share code, notes, and snippets.

@IvanPosohov
Created January 8, 2019 10:38
Show Gist options
  • Save IvanPosohov/bd382690df698d332eb24c081613828b to your computer and use it in GitHub Desktop.
Save IvanPosohov/bd382690df698d332eb24c081613828b to your computer and use it in GitHub Desktop.
inline fun <reified T> Activity.args(key: String? = null, defaultValue: T? = null): ReadWriteProperty<Activity, T> {
return BundleExtractorDelegate { thisRef, property ->
val bundleKey = key ?: property.name
extractFromBundle(thisRef.intent.extras, bundleKey, defaultValue)
}
}
import android.os.Bundle
import android.os.Parcelable
import java.io.Serializable
fun bundleOf(vararg params: Pair<String, Any?>): Bundle {
val b = Bundle()
for (p in params) {
val (k, v) = p
when (v) {
null -> b.putSerializable(k, null)
is Boolean -> b.putBoolean(k, v)
is Byte -> b.putByte(k, v)
is Char -> b.putChar(k, v)
is Short -> b.putShort(k, v)
is Int -> b.putInt(k, v)
is Long -> b.putLong(k, v)
is Float -> b.putFloat(k, v)
is Double -> b.putDouble(k, v)
is String -> b.putString(k, v)
is CharSequence -> b.putCharSequence(k, v)
is Parcelable -> b.putParcelable(k, v)
is Serializable -> b.putSerializable(k, v)
is BooleanArray -> b.putBooleanArray(k, v)
is ByteArray -> b.putByteArray(k, v)
is CharArray -> b.putCharArray(k, v)
is DoubleArray -> b.putDoubleArray(k, v)
is FloatArray -> b.putFloatArray(k, v)
is IntArray -> b.putIntArray(k, v)
is LongArray -> b.putLongArray(k, v)
is Array<*> -> {
@Suppress("UNCHECKED_CAST")
when {
v.isArrayOf<Parcelable>() -> b.putParcelableArray(k, v as Array<out Parcelable>)
v.isArrayOf<CharSequence>() -> b.putCharSequenceArray(k, v as Array<out CharSequence>)
v.isArrayOf<String>() -> b.putStringArray(k, v as Array<out String>)
else -> throw RuntimeException("Unsupported bundle component (${v.javaClass})")
}
}
is ShortArray -> b.putShortArray(k, v)
is Bundle -> b.putBundle(k, v)
else -> throw RuntimeException("Unsupported bundle component (${v.javaClass})")
}
}
return b
}
inline fun <reified T> extractFromBundle(bundle: Bundle?, key: String? = null, defaultValue: T? = null): T {
val result = bundle?.get(key) ?: defaultValue
if (result != null && result !is T) {
throw ClassCastException("Property for $key has different class type")
}
return result as T
}
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class BundleExtractorDelegate<in R, T>(private val initializer: (R, KProperty<*>) -> T) : ReadWriteProperty<R, T> {
private object EMPTY
private var value: Any? = EMPTY
override fun setValue(thisRef: R, property: KProperty<*>, value: T) {
this.value = value
}
override fun getValue(thisRef: R, property: KProperty<*>): T {
if (value == EMPTY) {
value = initializer(thisRef, property)
}
@Suppress("UNCHECKED_CAST")
return value as T
}
}
inline fun <T : Fragment> T.withArguments(vararg params: Pair<String, Any?>): T {
arguments = bundleOf(*params)
return this
}
inline fun <reified T> Fragment.args(key: String? = null, defaultValue: T? = null): ReadWriteProperty<Fragment, T> {
return BundleExtractorDelegate { thisRef, property ->
val bundleKey = key ?: property.name
extractFromBundle(thisRef.arguments, bundleKey, defaultValue)
}
}
companion object {
fun create(id: String) = SampleFragment().withArguments(
BundleKeys.ID to id
)
}
private val id by args<String>(BundleKeys.ID)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment