Normal 和 Single Expression 函数定义之间的差异
Differences between Normal and Single Expression function definitions
假设一个 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)
}
特别注意 choosePhotoButtonClick
和 takePhotoButtonClick
声明方式的区别。
构建此项目时,Android 的数据绑定对于 choosePhotoButtonClick
将正常工作,但对于 takePhotoButtonClick
会抛出错误,表示没有与预期的参考签名匹配的方法.假设这些方法在后台以相同的方式创建,这不应该发生,唉,肯定有一些区别。
这两种声明语法到底有什么区别? official Kotlin documentation 没有提到任何功能,只是它可以作为声明该方法的附加方式。
如果你在没有指定 return 类型的情况下使用花括号,你的函数正在隐式地重新调整 Unit
(这是 Kotlin for void
),所以你的方法:
fun choosePhotoButtonClick(v: View) {
onChoosePhotoButtonClicked?.invoke(v)
}
签名为:
fun choosePhotoButtonClick(v: View) : Unit
(IDE 会提示 return 类型 "Unit" 是多余的,可以省略)。
然而,对 shorthand 使用等号的函数会在右侧推断出 return 类型的表达式,例如:
fun itemCount() = items.size
会推断return类型的Int
,所以它的签名是:
fun itemCount() : Int
你的情况是:
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v)
函数可以是 return null
当 onTakePhotoButtonClicked
为 null 或 return 该方法的值 (Unit
),这意味着你的 takePhotoButtonClick
签名是:
fun takePhotoButtonClick(v: View) : Unit?
(OP)直接解决问题:
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v) ?: Unit
可以认为比大括号版本可读性差,但这意味着 return 类型的 Unit 而不是 Unit?并将通过数据绑定正确拾取。
假设一个 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)
}
特别注意 choosePhotoButtonClick
和 takePhotoButtonClick
声明方式的区别。
构建此项目时,Android 的数据绑定对于 choosePhotoButtonClick
将正常工作,但对于 takePhotoButtonClick
会抛出错误,表示没有与预期的参考签名匹配的方法.假设这些方法在后台以相同的方式创建,这不应该发生,唉,肯定有一些区别。
这两种声明语法到底有什么区别? official Kotlin documentation 没有提到任何功能,只是它可以作为声明该方法的附加方式。
如果你在没有指定 return 类型的情况下使用花括号,你的函数正在隐式地重新调整 Unit
(这是 Kotlin for void
),所以你的方法:
fun choosePhotoButtonClick(v: View) {
onChoosePhotoButtonClicked?.invoke(v)
}
签名为:
fun choosePhotoButtonClick(v: View) : Unit
(IDE 会提示 return 类型 "Unit" 是多余的,可以省略)。
然而,对 shorthand 使用等号的函数会在右侧推断出 return 类型的表达式,例如:
fun itemCount() = items.size
会推断return类型的Int
,所以它的签名是:
fun itemCount() : Int
你的情况是:
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v)
函数可以是 return null
当 onTakePhotoButtonClicked
为 null 或 return 该方法的值 (Unit
),这意味着你的 takePhotoButtonClick
签名是:
fun takePhotoButtonClick(v: View) : Unit?
(OP)直接解决问题:
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v) ?: Unit
可以认为比大括号版本可读性差,但这意味着 return 类型的 Unit 而不是 Unit?并将通过数据绑定正确拾取。