如何在数据绑定中不将参数传递给具有默认值的参数
How to NOT pass arguments to parameters with default values in Data Binding
是否可以在不传递参数的情况下使用 XML 中的默认参数调用 Kotlin 函数
这是我的视图模型:
class MyViewModel: ViewModel(){
fun doSomething(myVar: String = "defValue"){
}
}
XML:
....
<data>
<variable
name="viewModel"
type="com.example.MyViewModel" />
</data>
....
android:onClick="@{(view) -> viewModel.doSomething()}" --> ERROR
android:onClick="@{(view) -> viewModel.doSomething(`SomeString`)}" --> WORKING
....
当我使用数据绑定从 XML 调用 doSomething
方法 不带参数 时出现错误。
[databinding] {"msg":"cannot find method doSomething() in class com.example.MyViewModel","file":"app\src\main\res\layout\fragment_list.xml","pos":[{"line0":56,"col0":41,"line1":56,"col1":65}]}
好问题@DeveScie
失败的原因是doSomething()
没有任何参数的函数在字节码级别不存在。要理解,您需要查看您的 kotlin 代码如何转换为 Java 字节代码。
这是你的class的Java表示(省略了一些不相关的代码)
public final class MyViewModel {
public final void doSomething(@NotNull String myVar) {
Intrinsics.checkParameterIsNotNull(myVar, "myVar");
}
// $FF: synthetic method
public static void doSomething$default(MyViewModel var0, String var1, int var2, Object var3) {
if ((var2 & 1) != 0) {
var1 = "defValue";
}
var0.doSomething(var1);
}
}
这里是一个使用这个函数的 Kotlin 测试class
class TestClass {
fun testFunction() {
val vm = MyViewModel()
vm.doSomething()
vm.doSomething("Value")
}
}
这导致下面的 Java 代码
public final class TestClass {
public final void testFunction() {
MyViewModel vm = new MyViewModel();
MyViewModel.doSomething$default(vm, (String)null, 1, (Object)null);
vm.doSomething("Value");
}
}
如您所见,您在 kotlin 中的默认值实际上是通过以下方式调用的:
MyViewModel.doSomething$default(vm, (String)null, 1, (Object)null);
所以,你应该有一个单独的方法来处理其他情况。希望对你有帮助。
更新: 根据下面@Uli 的回答,另一种解决方案是将 @JvmOverloads
添加到您的 kotlin 函数中。
class MyViewModel {
@JvmOverloads
fun doSomething(myVar: String = "defValue") {
}
}
现在成为Java
中的关注者
public final class MyViewModel {
@JvmOverloads
public final void doSomething() {
doSomething$default(this, (String) null, 1, (Object) null);
}
@JvmOverloads
public final void doSomething(@NotNull String myVar) {
Intrinsics.checkParameterIsNotNull(myVar, "myVar");
}
// $FF: synthetic method
public static void doSomething$default(MyViewModel var0, String var1, int var2, Object var3) {
if ((var2 & 1) != 0) {
var1 = "defValue";
}
var0.doSomething(var1);
}
}
感谢 Uli 提醒我这个选项。
用 @JvmOverloads
注释你的 Kotlin 方法。 Java 没有默认参数的概念。此注解让 Kotlin 编译器生成一个无参数方法,因此您可以依次从 Java 和数据绑定 XML 调用它。
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-overloads/
是否可以在不传递参数的情况下使用 XML 中的默认参数调用 Kotlin 函数
这是我的视图模型:
class MyViewModel: ViewModel(){
fun doSomething(myVar: String = "defValue"){
}
}
XML:
....
<data>
<variable
name="viewModel"
type="com.example.MyViewModel" />
</data>
....
android:onClick="@{(view) -> viewModel.doSomething()}" --> ERROR
android:onClick="@{(view) -> viewModel.doSomething(`SomeString`)}" --> WORKING
....
当我使用数据绑定从 XML 调用 doSomething
方法 不带参数 时出现错误。
[databinding] {"msg":"cannot find method doSomething() in class com.example.MyViewModel","file":"app\src\main\res\layout\fragment_list.xml","pos":[{"line0":56,"col0":41,"line1":56,"col1":65}]}
好问题@DeveScie
失败的原因是doSomething()
没有任何参数的函数在字节码级别不存在。要理解,您需要查看您的 kotlin 代码如何转换为 Java 字节代码。
这是你的class的Java表示(省略了一些不相关的代码)
public final class MyViewModel {
public final void doSomething(@NotNull String myVar) {
Intrinsics.checkParameterIsNotNull(myVar, "myVar");
}
// $FF: synthetic method
public static void doSomething$default(MyViewModel var0, String var1, int var2, Object var3) {
if ((var2 & 1) != 0) {
var1 = "defValue";
}
var0.doSomething(var1);
}
}
这里是一个使用这个函数的 Kotlin 测试class
class TestClass {
fun testFunction() {
val vm = MyViewModel()
vm.doSomething()
vm.doSomething("Value")
}
}
这导致下面的 Java 代码
public final class TestClass {
public final void testFunction() {
MyViewModel vm = new MyViewModel();
MyViewModel.doSomething$default(vm, (String)null, 1, (Object)null);
vm.doSomething("Value");
}
}
如您所见,您在 kotlin 中的默认值实际上是通过以下方式调用的:
MyViewModel.doSomething$default(vm, (String)null, 1, (Object)null);
所以,你应该有一个单独的方法来处理其他情况。希望对你有帮助。
更新: 根据下面@Uli 的回答,另一种解决方案是将 @JvmOverloads
添加到您的 kotlin 函数中。
class MyViewModel {
@JvmOverloads
fun doSomething(myVar: String = "defValue") {
}
}
现在成为Java
中的关注者public final class MyViewModel {
@JvmOverloads
public final void doSomething() {
doSomething$default(this, (String) null, 1, (Object) null);
}
@JvmOverloads
public final void doSomething(@NotNull String myVar) {
Intrinsics.checkParameterIsNotNull(myVar, "myVar");
}
// $FF: synthetic method
public static void doSomething$default(MyViewModel var0, String var1, int var2, Object var3) {
if ((var2 & 1) != 0) {
var1 = "defValue";
}
var0.doSomething(var1);
}
}
感谢 Uli 提醒我这个选项。
用 @JvmOverloads
注释你的 Kotlin 方法。 Java 没有默认参数的概念。此注解让 Kotlin 编译器生成一个无参数方法,因此您可以依次从 Java 和数据绑定 XML 调用它。
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-overloads/