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

Time:03-25

In order to make a call to an API I'm collecting two values from the user:

  1. The input text
  2. A default string which lives in a variable and changes when the user select a filter in a radio group. Eg: "name", "status", "gender"

Once a got these values I need to call the next function.

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

Manually I would call viewModel.getCharacter(status = "alive") but I need a way to specify the named argument but itself because it depends what the user selected.

Any ideas?

edit: At the end this function calls a suspend function handled by 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

CodePudding user response:

It would be very difficult to specify optional function parameters by name (using reflection).

Instead, I would use a @QueryMap for this GET request, so you can specify the param name as a function parameter:

@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")

CodePudding user response:

Are you trying to call the function and use the default values, but provide one of them that's decided at runtime? As far as I'm aware you can't do that unfortunately - I've run into that limitation myself

Honestly for what you're doing, I wouldn't use default parameters - you basically have some type of filter, and some value for it, right? I'd just pass that into your function:

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

The benefit of this is because you're defining all your options in the enum, your radio button can use that enum internally too - you can put the display text as a property on the enum, and use that as a label in the UI, but you're actually working with and passing a FilterType that can be used directly, instead of a string that needs to be converted to a type or a property reference.

You could make getCharacter take a list of Filters if you want too, in case you ever want to implement multiple filters!

  • Related