双向数据绑定android:使用转换器检查

时间:2019-10-31 22:05:50

标签: android kotlin android-databinding

我有这个视图模型:

class MyViewModel : ViewModel() {
    var unit = "mi"
}

在我看来,我想选中viewModel.unit == "mi"复选框。这有效:

<layout>
    <data>
        <variable name="viewModel" type="com.example.MyViewModel" />
    </data>

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checked="@{viewModel.unit.equals(`mi`)}" />
</layout>

我想做一些花哨的双向绑定,所以当切换框时,视图模型中的属性也会更改。由于我需要在Boolean和String之间进行转换,因此看来转换器是完成这项工作的正确工具。这是新视图:

<layout>
    <data>
        <import type="com.example.Converters" />
        <variable name="viewModel" type="com.example.MyViewModel" />
    </data>

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checked="@={Converters.convertUnitToChecked(`mi`)}" />
</layout>

以下是转换器:

object Converters {

    @InverseMethod("convertCheckedToUnit")
    @JvmStatic
    fun convertUnitToChecked(unit: String): Boolean {
        return unit == "mi"
    }

    @JvmStatic
    fun convertCheckedToUnit(checked: Boolean): String {
        return if (checked) "mi" else "km"
    }
}

当我尝试构建它时,出现错误:

error: cannot generate view binders java.lang.IllegalStateException: expression does not support two-way binding
    at android.databinding.tool.expr.Expr.generateInverse(Expr.java:797)
    at android.databinding.tool.expr.MethodCallExpr.generateInverse(MethodCallExpr.java:311)
    at android.databinding.tool.InverseBinding.<init>(InverseBinding.java:65)
    at android.databinding.tool.BindingTarget.addInverseBinding(BindingTarget.java:70)
    at android.databinding.tool.LayoutBinder.<init>(LayoutBinder.java:134)
    at android.databinding.tool.DataBinder.<init>(DataBinder.java:60)
    at android.databinding.tool.CompilerChef.ensureDataBinder(CompilerChef.java:117)
    at android.databinding.tool.CompilerChef.sealModels(CompilerChef.java:369)
    at android.databinding.annotationprocessor.ProcessExpressions.writeResourceBundle(ProcessExpressions.java:244)
    at android.databinding.annotationprocessor.ProcessExpressions.onHandleStep(ProcessExpressions.java:126)
    at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.runStep(ProcessDataBinding.java:247)
    at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.access$000(ProcessDataBinding.java:232)
    at android.databinding.annotationprocessor.ProcessDataBinding.doProcess(ProcessDataBinding.java:113)
    at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:88)
    at org.jetbrains.kotlin.kapt3.base.incremental.IncrementalProcessor.process(incrementalProcessors.kt)
    at org.jetbrains.kotlin.kapt3.base.ProcessorWrapper.process(annotationProcessing.kt:147)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
    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.base.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:79)
    at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:35)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:230)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:188)
    at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:99)
    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:81)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:555)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:82)
    at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:107)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:546)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:177)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:164)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:54)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:84)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:42)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:104)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1558)
    at sun.reflect.GeneratedMethodAccessor113.invoke(Unknown Source)
    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:357)
    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:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

(我向转换器添加了@JvmStatic注释,因为没有这些注释,我会得到另一个错误:cannot find method convertUnitToChecked(java.lang.String)。)

据我所知,我的构建脚本包含所有必需的位:

apply plugin: 'kotlin-android'                       
apply plugin: 'kotlin-kapt'

android {
    ...
    dataBinding {
        enabled = true
    }
}

dependencies {
    ...
    kapt "com.android.databinding:compiler:$androidGradleVersion"
}

我不明白。我跟随these instructions到了那封信。我想念什么?

1 个答案:

答案 0 :(得分:0)

您正试图在双向绑定中使用 String 对象。单向绑定也不起作用,这意味着您的 UI 不会对更改做出反应,只会对最初收到的值做出反应。您需要一个用于单向和双向绑定的可观察对象,即 Observable fieldsLiveData, StateFlow