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

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/