>假设一个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>
以及随附的视图模型:
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
,说没有方法与预期的引用签名匹配。 假设这些方法在后台以相同的方式创建,这不应该发生,唉,一定有一些区别。
这两种声明语法到底有什么区别? 官方的 Kotlin 文档没有提到任何功能,只是说它可以作为声明该方法的另一种方式。
如果你使用大括号而不指定返回类型, 你的函数隐式重新调整Unit
(这是 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) = onTakePhotoButtonClicked?.invoke(v)
函数可以在onTakePhotoButtonClicked
为 null 时返回null
或返回该方法的值 (Unit
(,这意味着您的takePhotoButtonClick
签名是:
fun takePhotoButtonClick(v: View) : Unit?
(OP(直接解决问题:
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v) ?: Unit
可以认为比大括号版本可读性低,但这意味着返回类型为 Unit 而不是 Unit?,并且将被数据绑定正确拾取。