如果不为 null 或空 Kotlin,则将值作为参数传递

问题描述 投票:0回答:3
我有从文本输入中检索的文本值。我想让用户不填写这些输入。但如果用户尚未填写一个或多个值,我想显示这些输入的默认值。

我有一个看起来像这样的数据类:

@Parcelize data class Profile( val firstName: String = "", val lastName: String = "", val description: String = "", val imageUri: String = "" ) : Parcelable
单击后,我从 ViewModel 类中调用一个方法,并向其传递当前输入值,然后使用 Repository 类保存该值:

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 }
在另一个片段中,我使用此持久数据设置一些 UI 数据,如下所示:

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 个参数。我可以传递更少的参数,因为我有可选参数,但是如何根据值是否为非 null 或空有条件地将参数传递给 
createProfile
 。我当然可以为每个值创建检查,但是解决这个问题的最佳方法是什么?

更新

我认为我原来的问题不够清楚,因为我不仅将文本输入中的值传递到

createProfile

profileImageUri
 是类型为 
Uri?
 的类变量,最初设置为 
null
。用户可以选择图像,并且该变量将使用图像数据进行更新。我将图像数据传递并存储为字符串的原因是因为所有配置文件数据也会持久保存到 Firestore,因此字符串更易于使用。

android kotlin
3个回答
0
投票
与您自己的答案相比,我会创建一个辅助函数

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") )
编辑:考虑到更新,我会考虑

fun Any?.ifNullOrEmpty(default: String) = if (this == null || (this is CharSequence && this.isEmpty())) default else this.toString()
编辑2:为了处理@Gabriel Furstenheim的评论,将

createProfile

定义为

fun createProfile( firstName: String? = null, lastName: String? = null, description: String? = null, imageUri: String? = null ) { val profile = Profile( firstName.ifNullOrEmpty("John"), lastName.ifNullOrEmpty("Doe"), description.ifNullOrEmpty("Default Description"), imageUri.ifNullOrEmpty("") ) // Persist data }
或者如果您需要使用例如

firstName

两次,

fun createProfile( firstName: String? = null, lastName: String? = null, description: String? = null, imageUri: String? = null ) { val firstNameFinal = firstName.ifNullOrEmpty("John") val profile = Profile( firstNameFinal, ... ) // Persist data }
    

0
投票
我找到了解决方法。

事实证明,可以将

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
 为空,它不会尝试设置图像:

// ... 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
这里的主要问题是参数本身被混淆了。我仍然可以使用索引获取对各个参数的引用并使用它们进行操作,但效果不太好。


-1
投票
我认为你想要使用的是 Kotlin 中的

Elvis Operator?:

val test = exampleExpression ?: "alternative value"

如果

?:

 左侧的表达式为 
not null,则 elvis 运算符返回它,否则返回右侧的表达式。请注意,仅当左侧表达式为空时,才会计算右侧表达式。

viewModel.createProfile( etFirstName.text.toString() ?: "John", etLastName.text.toString() ?: "Doe", etProfileDescription.text.toString() ?: "Default Description", profileImageUri.toString() ?: "Default Uri" )
    
© www.soinside.com 2019 - 2024. All rights reserved.