Android 普通和单表达式函数定义之间的差异
假设有一个Android项目,其中有两个按钮的XML:Android 普通和单表达式函数定义之间的差异,android,kotlin,android-databinding,Android,Kotlin,Android Databinding,假设有一个Android项目,其中有两个按钮的XML: <layout> <data> <variable name="viewModel" type="com.package.package.UploadPhotoViewModel" /> </data> <LinearLayout android:layout_width="match_parent" androi
<layout>
<data>
<variable name="viewModel" type="com.package.package.UploadPhotoViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
android:padding="10dp">
<com.zoosk.zoosk.ui.widgets.ProgressButton
android:id="@+id/progressButtonChooseFromLibrary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.choosePhotoText}"
android:onClick="@{viewModel::choosePhotoButtonClick}"
android:visibility="@{viewModel.choosePhotoVisibility}" />
<com.zoosk.zoosk.ui.widgets.ProgressButton
android:id="@+id/progressButtonTakePhoto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.takePhotoText}"
android:onClick="@{viewModel::takePhotoButtonClick}"
android:visibility="@{viewModel.takePhotoVisibility}" />
</LinearLayout>
</layout>
特别注意choosePhotoButtonClick
和takePhotoButtonClick
的声明方式之间的差异
构建此项目时,Android的数据绑定将在choosePhotoButtonClick
中正常工作,但在takePhotoButtonClick
中抛出错误,表示没有与预期引用签名匹配的方法。假设这些方法在引擎盖下以相同的方式创建,这不应该发生,唉,肯定有一些不同
这两个声明语法到底有什么区别?没有提到任何函数,只是它可以作为声明该方法的附加方式。如果使用大括号而不指定返回类型,则函数将隐式重新调整
单元(这是Kotlin forvoid
),因此您的方法:
fun choosePhotoButtonClick(v: View) {
onChoosePhotoButtonClicked?.invoke(v)
}
签字人:
fun choosePhotoButtonClick(v: View) : Unit
(IDE将提示返回类型“Unit”是冗余的,可以使用)
但是,使用等号来简化函数会推断右侧表达式的返回类型,例如:
fun itemCount() = items.size
将推断Int
的返回类型,因此其签名为:
fun itemCount() : Int
fun takePhotoButtonClick(v: View) : Unit?
在您的情况下:
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v)
函数可以在onTakePhotoButtonClicked
为null时返回null
,或者返回该方法的值(Unit
),这意味着您的takePhotoButtonClick
签名为:
fun itemCount() : Int
fun takePhotoButtonClick(v: View) : Unit?
(OP)问题的直接解决方案:
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v) ?: Unit
可以认为它的可读性不如大括号版本,但这意味着返回类型是Unit而不是Unit?并且将通过数据绑定正确拾取。对于onGuidelinesLinkClicked
调用表示歉意,其目的是函数将各自调用各自的lambda,但您正确地假设签名是相同的。尽管很有趣。我知道单元
类型是Kotlin forvoid
,但我没有想到返回类型是单元
。也许可以通过在末尾添加?:Unit
来解决这个问题,以确保返回不是可选的?不管怎样,我都会试试。@SpyisSandvichUnit
被用来代替void
,但是它是,所以可空类型Unit?
是有效的。追加?:Unit
应该是一个有效的解决方案,但我个人认为使用大括号更具可读性。追加?:
在这种情况下确实有效。我选择使用它,因为整个想法是将onClick完全连接到传递到ViewModel的功能,它可能存在,也可能不存在,只需要几行就可以了。但是,如果我要对ViewModel中的功能做任何其他事情,那么我肯定会喜欢花括号版本。