找不到使用 lambda 的数据绑定事件的方法

Posted

技术标签:

【中文标题】找不到使用 lambda 的数据绑定事件的方法【英文标题】:Cannot find method for data binding event using lambda 【发布时间】:2018-06-25 19:01:52 【问题描述】:

到目前为止,我有使用 :: 表示法(即 android:onClick="@vm::doIt")的事件,但这需要 doIt 的签名才能具有不必要的 View 参数,我最终忽略了未使用的警告。我正在尝试清理它并移至 lambda 事件表示法(即 `android:onClick="@() -> vm.doIt(),但是编译器会引发异常。

layout.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="vm"
            type="com.myapp.ViewModel"/>
    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_
        android:layout_>
        <Button
            android:id="@+id/button"
            android:layout_
            android:layout_
            android:onClick="@() -> vm.buttonClicked()"
            <!--android:onClick="@vm::buttonClicked" worked with view param in buttonClicked in the viewModel -->
            android:text="@vm.buttonText"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </android.support.constraint.ConstraintLayout>
</layout>

ViewModel.kt

class ViewModel(): BaseObservable

    //Bindings - All works great!

    //Event handler... not found, worked with commented param and :: notation
    fun buttonClicked(/*view: View*/)
        //Do button click stuff
    

错误

e: java.lang.IllegalStateException: failed to analyze: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Cannot find method buttonClicked on ViewDataBinding file:/Users/.../app/src/main/res/layout/layout.xml loc:107:31 - 107:57 ****\ data binding error ****

at org.jetbrains.kotlin.analyzer.AnalysisResult.throwIfError(AnalysisResult.kt:57)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:137)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:158)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:61)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:107)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:51)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:92)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:386)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:96)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:892)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:96)
at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:919)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:891)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:385)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

Caused by: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Cannot find method buttonClicked on ViewDataBinding file:/Users/.../app/src/main/res/layout/layout.xml loc:107:31 - 107:57 ****\ data binding error ****

at android.databinding.tool.processing.Scope.assertNoError(Scope.java:112)
at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:91)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$200(JavacProcessingEnvironment.java:91)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.runContributingProcs(JavacProcessingEnvironment.java:627)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1033)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1198)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1068)
at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:73)
at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:42)
at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:205)
at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:166)
at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:82)
at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:96)
at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:106)
at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:83)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:376)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:67)
at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:96)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:367)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:132)
... 30 more

【问题讨论】:

【参考方案1】:

正如您在评论中提到的 android:onClick="@vm::doIt" 解决方案,您的 onClick 处理程序必须有一个 View 参数,即使您不使用它。

只要 lambda 接受 View 参数,通过 lambda 调用无参数 buttonClicked 方法的解决方法就可以很好地工作。这很容易。 Unused parameters to lambdas can be named "_" 为清楚起见。所以你的 onClick 处理程序可以这样配置:

android:onClick="@_ -> vm.buttonClicked()"

【讨论】:

按照您的建议更改 lambda 会导致相同的错误。 不确定,但也许android:onClick="@_: View-&gt; vm.buttonClicked()" 可以 不需要。我认为这个错误现在已经解决了:***.com/a/48308716/3195526 @PaulHicks View 参数指的是被点击的视图? 我就是这么读的。不过,我对 Android SDK 一无所知,我只知道如何在 Kotlin 中为 lambda 提供匿名参数:)【参考方案2】:

显然,数据绑定生成的类处于错误状态,无法正确重新生成,使缓存无效并清理解决了问题。

【讨论】:

【参考方案3】:

方法的签名必须在viewModel中相同,

我正在使用

android:onClick="@v -> viewModel.settingsClick()"

viewModel 中的方法是

 public void settingsClick() 
   ...

【讨论】:

以上是关于找不到使用 lambda 的数据绑定事件的方法的主要内容,如果未能解决你的问题,请参考以下文章

vue 和jquery 区别总结

Android 数据绑定:在生成的数据绑定文件中找不到 ...BindingImpl

如何解决:使用自定义视图实现双向数据绑定时“找不到属性'android:text'的getter”?

Android 数据绑定:如何避免“找不到 KaptTask”警告

找不到与参考绑定的源...数据绑定ListView问题

为什么ajax加载出来的html,无法用选择器绑定事件?