正则表达式和单表达式函数定义之间的差异

时间:2018-06-26 17:20:53

标签: android kotlin android-databinding

假设一个Android项目中有两个按钮的XML:

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

以及随附的ViewModel:

class UploadPhotoViewModel(resources: Resources) {
    var onChoosePhotoButtonClicked: ((View) -> Unit)? = null
    var onTakePhotoButtonClicked: ((View) -> Unit)? = null

    fun choosePhotoButtonClick(v: View) {
        onChoosePhotoButtonClicked?.invoke(v)
    }
    fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v)
}

特别注意choosePhotoButtonClicktakePhotoButtonClick的声明方式。

在构建此项目时,Android的数据绑定将在choosePhotoButtonClick上正常工作,但会在takePhotoButtonClick上引发错误,表示没有与预期参考签名匹配的方法。假设这些方法是在幕后以相同的方式创建的,那么这种情况就不会发生,因为一定会有区别。

这两种声明语法到底有什么区别? official Kotlin documentation没有提及任何功能,只是提及它可以作为声明该方法的另一种方式。

1 个答案:

答案 0 :(得分:0)

如果使用花括号而不指定返回类型,则您的函数将隐式调整Unit(这是void的Kotlin),因此您的方法是

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) = onTakePhotoButtonClicked?.invoke(v)

函数可以在null为空时返回onTakePhotoButtonClicked或该方法的返回值(Unit),这意味着您的takePhotoButtonClick签名为:

fun takePhotoButtonClick(v: View) : Unit?

(OP)直接解决问题:

fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v) ?: Unit

可以被认为比花括号版本的可读性差,但这意味着单元的返回类型而不是单元吗?并将通过数据绑定正确地拾取。