Flutter MethodCall non-nil check in kotlin way

Issue

I tried to make a MethodCall type judgement function using kotlin, but it return a type mismatch for me, how should I fix with it?

import java.util.Objects

import io.flutter.plugin.common.MethodCall

class Utils private constructor() {
    companion object {
        fun getDoubleArgument(call: MethodCall, argument: String?): Double {
            return try {
                if (call.argument<Any>(argument) is Double) {
                    Objects.requireNonNull(call.argument<Double>(argument))!!  // The call.argument return Double? type, but when I add !! assert, it report Unnecessary non-null assertion (!!).
                } else if (call.argument<Any>(argument) is Long) {
                    val l = Objects.requireNonNull(call.argument<Long>(argument))
                    l!!.toDouble()
                } else if ...
        }

Solution

I don’t use Flutter, so please excuse any errors.

You don’t need Objects.requireNonNull() in Kotlin, because !! already does the exact same thing as requireNonNull(), except that it throws KotlinNullPointerException instead of NullPointerException. The reason it’s not working is that Kotlin doesn’t know that the Java method is guaranteed to return a non-null value.

class Utils private constructor() {
    companion object {
        fun getDoubleArgument(call: MethodCall, argument: String?): Double {
            return try {
                if (call.argument<Any>(argument) is Double) {
                    call.argument<Double>(argument)!!
                } else if (call.argument<Any>(argument) is Long) {
                    call.argument<Long>(argument)!!.toDouble()
                } else if ...
        }

It would be better to get the argument one time and using that value. Then you can rely on Kotlin smart-casting to simplify the code:

class Utils private constructor() {
    companion object {
        fun getDoubleArgument(call: MethodCall, argument: String?): Double {
            val arg = call.argument<Any>(argument)
            return try {
                if (arg is Double) {
                    arg
                } else if (arg is Long) {
                    arg.toDouble()
                } // ...
                else if (arg == null) {
                    0.0
                } else {
                    error("unsupported argument type")
                }
        }

You can use a when statement instead of a chain of else if to make it easier to read:

class Utils private constructor() {
    companion object {
        fun getDoubleArgument(call: MethodCall, argument: String?): Double {
            val arg = call.argument<Any>(argument)
            return try {
                when (arg) {
                    is Double -> arg
                    is Long -> arg.toDouble()
                    // ...
                    null -> 0.0
                    else -> error("unsupported argument type")
                }
            }
        }

Answered By – Tenfour04

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *