Skip to content

Instantly share code, notes, and snippets.

@Wavesonics
Created December 13, 2018 20:00
Show Gist options
  • Save Wavesonics/7594398001c6e8cd81cdfa7bf44117fd to your computer and use it in GitHub Desktop.
Save Wavesonics/7594398001c6e8cd81cdfa7bf44117fd to your computer and use it in GitHub Desktop.
Kotlin newInstance() Fragment pattern
/**
* Eases the Fragment.newInstance ceremony by marking the fragment's args with this delegate
* Just write the property in newInstance and read it like any other property after the fragment has been created
*
* Inspired by Adam Powell, he mentioned it during his IO/17 talk about Kotlin
*/
class Argument<T : Any> : kotlin.properties.ReadWriteProperty<Fragment, T>
{
var value: T? = null
override operator fun getValue(thisRef: android.support.v4.app.Fragment, property: kotlin.reflect.KProperty<*>): T
{
if(value == null)
{
val args = thisRef.arguments ?: throw IllegalStateException(
"Cannot read property ${property.name} if no arguments have been set")
@Suppress("UNCHECKED_CAST")
value = args.get(property.name) as T
}
return value ?: throw IllegalStateException("Property ${property.name} could not be read")
}
override operator fun setValue(thisRef: android.support.v4.app.Fragment, property: kotlin.reflect.KProperty<*>, value: T)
{
if(thisRef.arguments == null) thisRef.arguments = android.os.Bundle()
val args = thisRef.arguments
args?.let {
val key = property.name
when(value)
{
is String -> args.putString(key, value)
is Int -> args.putInt(key, value)
is Short -> args.putShort(key, value)
is Long -> args.putLong(key, value)
is Byte -> args.putByte(key, value)
is ByteArray -> args.putByteArray(key, value)
is Char -> args.putChar(key, value)
is CharArray -> args.putCharArray(key, value)
is CharSequence -> args.putCharSequence(key, value)
is Float -> args.putFloat(key, value)
is Bundle -> args.putBundle(key, value)
is Binder -> BundleCompat.putBinder(args, key, value)
is android.os.Parcelable -> args.putParcelable(key, value)
is java.io.Serializable -> args.putSerializable(key, value)
else -> throw IllegalStateException(
"Type ${value.javaClass.name} of property ${property.name} is not supported")
}
}
}
}
class NullableArgument<T> : kotlin.properties.ReadWriteProperty<Fragment, T?>
{
var value: T? = null
override operator fun getValue(thisRef: android.support.v4.app.Fragment, property: kotlin.reflect.KProperty<*>): T?
{
// If the fragment does not have any arguments, we assume that no properties were provided
if(thisRef.arguments == null)
{
return null
}
if(value == null)
{
val args = thisRef.arguments ?: throw IllegalStateException(
"Cannot read property ${property.name} if no arguments have been set")
@Suppress("UNCHECKED_CAST")
value = args.get(property.name) as T?
}
return value
}
override operator fun setValue(thisRef: android.support.v4.app.Fragment, property: kotlin.reflect.KProperty<*>, value: T?)
{
if(value == null)
{
return
}
if(thisRef.arguments == null) thisRef.arguments = android.os.Bundle()
val args = thisRef.arguments
args?.let {
val key = property.name
when(value)
{
is String -> args.putString(key, value)
is Int -> args.putInt(key, value)
is Short -> args.putShort(key, value)
is Long -> args.putLong(key, value)
is Byte -> args.putByte(key, value)
is ByteArray -> args.putByteArray(key, value)
is Char -> args.putChar(key, value)
is CharArray -> args.putCharArray(key, value)
is CharSequence -> args.putCharSequence(key, value)
is Float -> args.putFloat(key, value)
is Bundle -> args.putBundle(key, value)
is Binder -> BundleCompat.putBinder(args, key, value)
is android.os.Parcelable -> args.putParcelable(key, value)
is java.io.Serializable -> args.putSerializable(key, value)
is Any -> throw IllegalStateException(
"Type ${value.javaClass.name} of property ${property.name} is not supported")
else -> throw IllegalStateException(
"Property ${property.name} is not supported")
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment