【问题标题】:How to use companion objects on xml layout?如何在 xml 布局上使用伴随对象?
【发布时间】:2018-06-20 14:07:56
【问题描述】:

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

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 布局中使用伴随对象?我该如何进行?提前感谢您的帮助:)

【问题讨论】:

  • 上下文是什么?你为什么要这个
  • 好吧,我想要一个 if 将一个值与一个常数进行比较,例如:android:visibility="@{delivery.status == Status.Companion.finished ? View.VISIBLE : View.GONE}" 我不知道,我只是编造的,但是像这样

标签: android kotlin android-databinding


【解决方案1】:

为了访问Companion 对象的属性和方法,不需要拥有 Parent 对象的实例。 伴随对象已经实例化,因此您可以直接访问该实例。

我们需要使用&lt;variable&gt;,而不是使用&lt;import&gt;(它是Java 的自然翻译),因为我们实际上想在我们的XML 布局中使用(已经实例化的)Companion 对象。

如下导入您的 Companion 对象

给定 Kotlin 类:

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
    }
}

布局:

    <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>

片段:

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

【讨论】:

  • 这只是答案。谢谢。
【解决方案2】:

如果你用@JvmStatic注释你的方法/属性,你可以去掉Companion关键字

【讨论】:

    【解决方案3】:

    在 XML 中只需在字段名称前添加 Companion,例如:

    在 ViewModel 中

    package com.example.project
    
    class MyViewModel {
        companion object {
            var leText = "text"
        }
    
        var leColor = ...
    }
    

    在 XML 中

    <data>
        <import type="android.view.View" />
        <variable 
            name="context"
            type="com.example.project.MyViewModel" />
    </data>
    
    <TextView
        ...
        android:text="@{context.Companion.leText}"
        android:color="@{context.leColor}"/>
    

    【讨论】:

    • 我没有实例 :(
    【解决方案4】:

    要访问您的财产,请执行以下操作:

    用注释你的伴随对象属性 @JvmStatic

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

    然后从绑定的 TextView 中删除“Companion”:

    改变

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

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

    【讨论】:

      【解决方案5】:

      TL;DR:

      替换

      android:text="@{MyClass.Companion.SomeProperty}"
      

      android:text="@{MyClass.Companion.getSomeProperty()}"
      

      说明:

      您的问题是您试图完全按照其名称引用 Kotlin 对象,但这不是 Kotlin 编译器在 Java 中生成属性的方式。相反,它将使用作为“get”函数的 Java 约定进行转换。

      您可以通过反编译 Kotlin 字节码来了解此名称的外观。

      1. 打开要查看其字节码的 Kotlin 类。
      2. 打开Tools > Kotlin > Show Kotlin Bytecode
      3. 在打开的侧面板中,点击左上角的Decompile 按钮。

      这将显示 Kotlin 类的 Java 等效项,包括伴随属性的全名。

      奖金

      也就是说,您可能更愿意将该字段作为属性引用,在这种情况下,您只需将const 键盘附加到属性声明即可。

      const val SomeProperty = "hey"
      

      这样,编译器会将字段生成为public static 字段,在Companion 之外,您可以将xml 更新为:

      android:text="@{MyClass.SomeProperty}"
      

      这几乎就是你在 Java 中的做法。

      希望有帮助!

      【讨论】:

        【解决方案6】:

        还有一种方法: 在课堂上

        const val SomeProperty = "hey"
        class MyClass {}
        

        在 XML 中

          <data>
            <import type="package.MyClassKt"/>
          </data>
        
          <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@{MyClassKt.SomeProperty}"/>
        

        【讨论】:

          【解决方案7】:

          我浏览了所有这些答案,我必须想出自己的解决方案。

          const val 修饰符标记常量(const 是关键),只需导入“父”类(在您的情况下为 MyClass),您不需要单词 Companion

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

          XML

            <data>
              <import type="package.MyClass"/>
            </data>
          
            <TextView
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:text="@{MyClass.SomeProperty}"/>
          
          </layout>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-12-14
            • 2016-11-02
            • 1970-01-01
            • 2016-08-09
            • 1970-01-01
            • 2021-12-15
            相关资源
            最近更新 更多