Передавать значения как параметры, если они не пустые или пустые Kotlin - PullRequest
1 голос
/ 02 августа 2020

У меня есть текстовые значения, которые я извлекаю из текстовых полей. Я хочу разрешить пользователю не заполнять эти поля. Но если пользователь не заполнил одно или несколько значений, я хочу отобразить значения по умолчанию для этих входов.

У меня есть класс данных, который выглядит примерно так:

@Parcelize
data class Profile(
    val firstName: String = "",
    val lastName: String = "",
    val description: String = "",
    val imageUri: String = ""
) : Parcelable

При нажатии I вызвать метод из моего класса ViewModel и передать ему текущие входные значения, которые затем сохраняются с использованием класса репозитория:

viewModel.createProfile(
   etFirstName.text.toString(),
   etLastName.text.toString(),
   etProfileDescription.text.toString(),
   profileImageUri.toString()
)


// The createProfile function itself
fun createProfile(
    firstName: String = "John",
    lastName: String = "Doe",
    description: String = "Default Description",
    imageUri: String = ""
) {
    val profile = Profile(firstName, lastName, description, imageUri)
    // Persist data
}

В другом фрагменте я установил некоторые данные пользовательского интерфейса, используя эти постоянные данные, например:

private fun observeProfile() {
    viewModel.getProfile()

    viewModel.profile.observe(viewLifecycleOwner, Observer {
        val profile = it
        tvName.text = getString(R.string.profile_name, profile.firstName, profile.lastName)
        tvDescription.text = profile.description
        ivProfileImage.setImageURI(Uri.parse(profile.imageUri))
    })
}

Итак, в настоящее время createProfile ожидает 4 аргумента. Я могу передать меньше, потому что у меня есть необязательные параметры, но как я могу условно передать аргументы в createProfile в зависимости от того, является ли значение ненулевым или пустым. Я, конечно, могу создавать проверки для каждого значения, но как лучше всего подойти к этому?

Обновление

Не думаю, что я достаточно ясно выразился в своем исходный вопрос, потому что я не только передаю значения из текстовых полей в createProfile. profileImageUri - это переменная класса типа Uri?, для которой изначально установлено значение null. Пользователь может выбрать изображение, и эта переменная обновляется данными изображения. Причина, по которой я передаю и сохраняю данные изображения в виде строки, заключается в том, что все данные профиля также сохраняются в Firestore, поэтому со строками легче работать.

Ответы [ 3 ]

1 голос
/ 03 августа 2020

По сравнению с вашим собственным ответом, я бы создал вспомогательную функцию

fun CharSequence?.ifNullOrEmpty(default: String) = if (this.isNullOrEmpty()) default else this.toString()

и использовал бы ее как

viewModel.createProfile(
    etFirstName.text.ifNullOrEmpty("John"),
    etLastName.text.ifNullOrEmpty("Doe"),
    etProfileDescription.text.ifNullOrEmpty("Default Description"),
    profileImageUri.ifNullOrEmpty("Default Uri")
)

EDIT: с учетом обновления я бы рассмотрел

fun Any?.ifNullOrEmpty(default: String) = 
    if (this == null || (this is CharSequence && this.isEmpty())) 
        default 
    else 
        this.toString()
0 голосов
/ 02 августа 2020

Я нашел обходной путь.

Оказывается, можно передать if-else операторы в качестве параметров, потому что if операторы являются выражениями в Kotlin:

viewModel.createProfile(
    if (!etFirstName.text.isNullOrEmpty()) etFirstName.text.toString() else "John",
    if (!etLastName.text.isNullOrEmpty()) etLastName.text.toString() else "Doe",
    if (!etProfileDescription.text.isNullOrEmpty()) etProfileDescription.text.toString() else "Default Description",
    if (profileImageUri != null) profileImageUri.toString() else ""
)

Использование при таком подходе мне также не нужно устанавливать значения по умолчанию для моих переменных data class и параметров функции createProfile.

Я дополнительно добавил проверку в свою функцию observeProfile, поэтому если profileImageUri будет null, он не будет пытаться установить изображение:

// ...
if (profile.imageUri.isNotEmpty()) {
    ivProfileImage.setImageURI(Uri.parse(profile.imageUri))
}
// ...

Моя первоначальная идея кажется невозможной с использованием класса данных. Кажется возможным использовать обычный класс и varargs, но есть проблемы:

@Parcelize
class Profile(
    vararg val params: String
) : Parcelable

...

val params = arrayOfValues.filter{ !it.isNullOrBlank() } // filter out all unwanted data
val profile = Profile(*params) // pass every param separately using spread operator

Основная проблема здесь в том, что сами параметры запутываются. Я все еще могу получить ссылку на отдельные параметры с помощью индекса и что-то с ними делать, но это работает не так хорошо.

0 голосов
/ 02 августа 2020

Я думаю, что вы хотите использовать Оператор Элвиса в Kotlin: ?:.

val test = exampleExpression ?: "alternative value"

Если выражение слева от ?: is not null , оператор elvis возвращает его, иначе он возвращает выражение справа. Обратите внимание, что выражение в правой части оценивается только в том случае, если левая часть равна нулю.

viewModel.createProfile(
   etFirstName.text.toString() ?: "John",
   etLastName.text.toString() ?: "Doe",
   etProfileDescription.text.toString() ?: "Default Description",
   profileImageUri.toString() ?: "Default Uri"
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...