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

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

提问人:Alejandro Agüero 提问时间:3/25/2022 最后编辑:Alejandro Agüero 更新时间:3/25/2022 访问量:200

问:

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

  1. 输入文本
  2. 一个默认字符串,它位于变量中,当用户在单选按钮组中选择筛选器时会发生变化。例如:“姓名”、“状态”、“性别”

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

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

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

有什么想法吗?

edit:最后,此函数调用由 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
Android Kotlin 参数传递

评论

0赞 Tenfour04 3/25/2022
这个函数的内部是什么样子的?尝试通过反射来使用参数名称来做到这一点将是非常复杂的。
0赞 Alejandro Agüero 3/25/2022
检查帖子:)中的编辑

答:

1赞 Tenfour04 3/25/2022 #1

按名称指定可选函数参数(使用反射)将非常困难。

相反,我将使用一个来表示这个 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")
1赞 cactustictacs 3/25/2022 #2

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

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

// 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

如果你愿意,你也可以做一个列表,以防你想实现多个过滤器!getCharacterFilter

0赞 lukas.j 3/25/2022 #3

使用反射:

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