如何不将参数传递给数据绑定中具有默认值的参数



是否可以在不传递参数的情况下使用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}]}

@JvmOverloads注释你的 Kotlin 方法。Java 没有默认参数的概念。此注解让 Kotlin 编译器生成一个无参数方法,因此您可以依次从 Java 和数据绑定 XML 调用它。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-overloads/

很好的问题@DeveScie

失败的原因是字节码级别不存在没有任何参数函数的doSomething()。要理解,您需要了解您的 kotlin 代码是如何转换为 Java 字节码的。

这是类的 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 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);

因此,对于其他情况,您应该使用单独的方法。希望对您有所帮助。

>UPDATE:根据下面@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 提醒我这个选项。

最新更新