如何调用作为另一个函数结果的特定命名参数?科特林

How to call specific named argument which is a result of another function? Kotlin

为了调用 API,我从用户那里收集了两个值:

  1. 输入文字
  2. 一个默认字符串,它存在于变量中并在用户 select 无线电组中的过滤器时发生变化。例如:“姓名”、“身份”、“性别”

获得这些值后,我需要调用下一个函数。

    fun getCharacter(name: String? = null, status: String? = null, species: String? = null, type: String? = null, gender: String? = null) {
            //code
}

我会手动调用 viewModel.getCharacter(status = "alive") 但我需要一种方法来指定命名参数本身,因为它取决于用户 selected.

有什么想法吗?

编辑:最后这个函数调用了一个由 retrofit

处理的挂起函数
@GET("character/")
   suspend fun getCharacter(
           @Query ("name") name: String?,
           @Query("status") status: String?,
           @Query("species") species: String?,
           @Query("type") type: String?,
           @Query("gender") gender: String?,

   ): CharacterResponse

很难通过名称指定可选函数参数(使用反射)。

相反,我会为此 GET 请求使用 @QueryMap,因此您可以将参数名称指定为函数参数:

@GET("character/")
suspend fun getCharacter(
    @QueryMap params: Map<String, String>
): CharacterResponse
suspend fun getCharacter(paramName: String, paramValue: String): CharacterResponse {
    // ...
    return service.getCharacter(mapOf(paramName to paramValue))
}
viewModel.getCharacter("status", "alive")

您是否尝试调用该函数并使用默认值,但提供其中一个在 运行 时决定的值?据我所知,不幸的是你不能那样做 - 我自己 运行 遇到了这个限制

老实说,对于您正在做的事情,我不会使用默认参数 - 您基本上有某种类型的过滤器,并且有一些价值,对吧?我只是将其传递到您的函数中:

// I'm not entirely sure what string data you're passing but hopefully this
// makes enough sense that you can work out how to apply it to your thing
data class Filter(val type: FilterType, val value: String = type.defaultString)

enum class FilterType(val defaultString: String) {
    NAME("name"), STATUS("alive")
}

fun getCharacter(filter: Filter) {
   // do the thing
}

这样做的好处是因为您在枚举中定义了所有选项,您的单选按钮也可以在内部使用该枚举 - 您可以将显示文本作为枚举上的 属性,并且将其用作 UI 中的标签,但您实际上正在处理并传递可以直接使用的 FilterType,而不是需要转换为类型或 属性参考。

如果您也愿意,您可以让 getCharacter 获取 Filter 的列表,以防您想要实施多个过滤器!

使用反射:

import kotlin.reflect.KParameter.Kind.INSTANCE
import kotlin.reflect.full.memberFunctions

fun callFunction(instance: Any, functionName: String, arguments: Map<String, String?>) {
  val function = instance::class.memberFunctions.first { it.name == functionName }
  function.callBy(function.parameters.associateWith { if (it.kind == INSTANCE) instance else arguments[it.name] })
}

class ViewModel {
  fun getCharacter(name: String? = null, status: String? = null, species: String? = null, type: String? = null, gender: String? = null) {
    println("name: $name")
    println("status: $status")
    println("species: $species")
    println("type: $type")
    println("gender: $gender")
  }
}

val viewModel = ViewModel()

callFunction(viewModel, "getCharacter", mapOf("species" to "animal", "type" to "mammal"))

输出:

name: null
status: null
species: animal
type: mammal
gender: null