Reified: To make something abstract more concrete or real is highly recommended for Android development. This article introduces three special uses as follows:

1. No longer need to pass the clazz parameter

For example, when we define an extension function to start an Activity, we pass the Class

parameter:

// Function
private fun <T : Activity> Activity.startActivity(context: Context, clazz: Class<T>) {
    startActivity(Intent(context, clazz))
}

// Caller
startActivity(context, NewActivity::class.java)
Copy the code

Reified way

Use Reified to simplify generic parameters by adding type passing

// Function
inline fun <reified T : Activity> Activity.startActivity(context: Context) {
    startActivity(Intent(context, T::class.java))
}

// Caller
startActivity<NewActivity>(context)
Copy the code

2. Unsafe transitions

In Kotlin, use the secure conversion operator as? Which can return NULL on failure. Implement the following function that we think will safely fetch data or return NULL

// Function
fun <T> Bundle.getDataOrNull(a): T? {
    return getSerializable(DATA_KEY) as? T
}

// Caller
valbundle: Bundle? = Bundle() bundle? .putSerializable(DATA_KEY,"Testing")
valstrData: String? = bundle? .getDataOrNull()val intData: Int? = bundle? .getDataOrNull()// Crash
Copy the code

However, if the data obtained is not of the type it expects, the function crashes. Therefore, to obtain data safely, modify the previous function as follows:

// Function
fun <T> Bundle.getDataOrNull(clazz: Class<T>): T? {
    val data = getSerializable(DATA_KEY)
    return if (clazz.isInstance(data)) {
        data as T
    } else {
        null}}// Caller
valbundle: Bundle? = Bundle() bundle? .putSerializable(DATA_KEY,"Testing")
valstrData: String? = bundle? .getDataOrNull(String::class.java)
val intData: Int? = bundle? .getDataOrNull(String::class.java) / /Null
Copy the code

This is not very friendly, not only in the way the function is implemented, but also in passing additional Clazz arguments.

Reified way

Use Reified to simplify generic parameters and ensure as? Conversion security

// Function
private inline fun <reified T> Bundle.getDataOrNull(a): T? {
    return getSerializable(DATA_KEY) as? T
}

// Caller
valbundle: Bundle? = Bundle() bundle? .putSerializable(DATA_KEY,"Testing")
valstrData: String? = bundle? .getDataOrNull()val intData: Int? = bundle? .getDataOrNull()// Null
Copy the code

3. Function overloading with different return types

Implement a function that computes DP to pixels and returns an Int or Float. In this case, function overloading comes to mind, as follows:

fun Resources.dpToPx(value: Int): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        value.toFloat(), displayMetrics)
}

fun Resources.dpToPx(value: Int): Int {
    val floatValue: Float = dpToPx(value)
    return floatValue.toInt()
}
Copy the code

However, this will result in compile-time errors. The reason is that function overloading depends only on parameter counts and types, not return types.

Reified way

Using Reified, you can implement different return type function overloading

inline fun <reified T> Resources.dpToPx(value: Int): T {
    val result = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        value.toFloat(), displayMetrics)

    return when (T::class) {
        Float: :class -> result as T
        Int: :class -> result.toInt(a)as T
        else -> throw IllegalStateException("Type not supported")}}// Caller
val intValue: Int = resource.dpToPx(64)
val floatValue: Float = resource.dpToPx(64)
Copy the code

From the three examples above, it’s clear that Reified makes Kotlin more user-friendly to use. If there are other scenarios where reified is used, please share.