Home > database >  Kotlin call function with parameter by using Any is xxx || Any is yyy not working
Kotlin call function with parameter by using Any is xxx || Any is yyy not working

Time:09-11

my variable passed into my class constructor can be either Fragment or AppCompactActivity, so I use the following code to check wther it's valid in Glide's .with function.

class XXXX(private val parent: Any)

if (parent is AppCompatActivity || parent is Fragment) {
            // Load User Avatar
            Glide.with(parent)
                .load(dataSet[position].user.avatar)
                .into(viewHolder.userAvatar)
        }

when I only use parent is AppCompactActivity or parent is Fragement, the code works just fine. However, when I use an or operator, it gives me the following errors:

None of the following functions can be called with the arguments supplied.
with(Activity) defined in com.bumptech.glide.Glide
with(android.app.Fragment) defined in com.bumptech.glide.Glide
with(Context) defined in com.bumptech.glide.Glide
with(View) defined in com.bumptech.glide.Glide
with(androidx.fragment.app.Fragment) defined in com.bumptech.glide.Glide
with(FragmentActivity) defined in com.bumptech.glide.Glide

CodePudding user response:

Kotlin is a static, strongly typed language, so it always requires to understand what is the type of an object and which function exactly is invoked. Well, this is only partially true, it supports virtual functions, but Glide.with() is overloaded, so it has to be resolved at compile time.

If you use parent is AppCompactActivity then the compiler is sure parent is AppCompactActivity, so when you invoke Glide.with(parent) it knows it has to use Glide.with(FragmentActivity). Similarly, if you use parent is Fragement then it knows it has to invoke Glide.with(Fragment).

If you use parent is AppCompatActivity || parent is Fragment then the compiler could assume parent is either AppCompatActivity or Fragment, but it still doesn't know, which Glide.with() function to use. This has to be decided at runtime, but the compiler has to resolve this call at compile time, which is not possible.

To fix the problem, you need to provide two separate control flow paths to use the proper with() function:

val glide = when (parent) {
    is AppCompatActivity -> Glide.with(parent)
    is Fragment -> Glide.with(parent)
    else -> ... // throw exception?
}
glide.load(dataSet[position].user.avatar)
    .into(viewHolder.userAvatar)

It looks like we execute exactly the same code for both cases, but in fact this is not true. If you ctrl click on both with() functions, you'll see they point at different implementations.

If you do this often in your code, you can create an utility function:

fun test() {
    glideWith(parent)
        .load(dataSet[position].user.avatar)
        .into(viewHolder.userAvatar)
}

fun glideWith(context: Any) = when (context) {
    is AppCompatActivity -> Glide.with(parent)
    is Fragment -> Glide.with(parent)
    else -> ... // throw exception?
}
  • Related