首页 > 解决方案 > 如何在 xml 布局上使用伴随对象?

问题描述

我正在尝试在布局中使用伴随对象属性,但编译器无法识别它。

Kotlin 类

class MyClass {
  companion object {
    val SomeProperty = "hey"
  }
}

XML 布局

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

  <data>
    <import type="package.MyClass"/>
  </data>

  <TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="@{MyClass.Companion.SomeProperty}"/>

</layout>

我得到了这个错误:

e: java.lang.IllegalStateException: failed to analyze: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Could not find accessor package.MyClass.Companion.SomeProperty file:/path/to/my/layout.xml loc:21:67 - 21:103 ****\ data binding error ****

    at org.jetbrains.kotlin.analyzer.AnalysisResult.throwIfError(AnalysisResult.kt:57)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:138)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:154)
    ...
Caused by: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Could not find accessor package.MyClass.Companion.SomeProperty file:/path/to/my/layout.xml loc:21:67 - 21:103 ****\ data binding error ****

    at android.databinding.tool.processing.Scope.assertNoError(Scope.java:112)
    at android.databinding.annotationprocessor.ProcessDataBinding.doProcess(ProcessDataBinding.java:101)
    at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:65)
    ...

我尝试使用companion而不是Companion,但没有运气。

是否可以在带有数据绑定的 xml 布局上使用伴随对象?我该如何进行?在此先感谢您的帮助:)

标签: androidkotlinandroid-databinding

解决方案


In order to access Companion object attributes and methods, it is NOT required to have an instance of the Parent object. Companion object are already instantiated, therefore you can access the instance directly.

Instead of using <import> (which is the natural translation from Java), we need to use <variable>, because we actually want to use the (already instantiated) Companion object into our XML Layout.

Import your Companion object as follow

Given Kotlin class:

package com.example.project

class MyViewModel {
    companion object {
        // it is only working with val and var
        // const val wouldn't work
        val MAX_LENGTH = 10
    }
}

Layout:

    <data>
        <!-- Declare your "variable" that hold the Companion object itself -->
        <variable name="myViewModelStatic" type="com.example.project.MyViewModel.Companion" />
    </data>

    <!-- then use the myViewModelStatic to access "static" properties of MyViewModel -->
    <EditText
    ...
    android:maxLength="@{ myViewModelStatic.MAX_LENGTH }"
    />
</layout>

Fragment:

class MyFragment {
    ...
    onViewCreated(...) {
         // now bind the companion object to the variable declared in the XML
         binding.myViewModelStatic = TransferUseCase.Companion
    }
    ...
}

推荐阅读