【问题标题】:Android Data binding for child class子类的Android数据绑定
【发布时间】:2018-04-16 13:30:09
【问题描述】:

我要上课:

public class Product {
  private int id;
  private String title;
  .............
  .............
}

其他类如下:

public class CatalogItem extends Product {
   private int price;
   private String[] colors;
   .............
   .............
}

在布局中,我想访问子类和父类的所有属性。

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

    <data>

        <variable
            name="catalogItem "
            type="com.appdemo.db.entity.CatalogItem" />
   </data>
   <TextView
            android:id="@+id/productIdTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@{((com.appdemo.db.entity.Product) catalogItem).id}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
     ..................
     ..................
</layout>

但是在数据绑定的情况下,无法访问父类的属性。访问父类属性的正确方法是什么?

【问题讨论】:

  • 您可以轻松地以编程方式(动态)来代替吗?是否可以?在 xml 中设计模式,然后在 Java 中动态添加您的项目。
  • 为什么要单独设置各个属性,那Data Binding有什么用,@Fatmajk

标签: android data-binding parent-child


【解决方案1】:

我相信您的问题是您的访问器不是公开的,并且像您进行类型转换一样被标记为@Bindable,这很好,但是如果您发布 Pseduo 代码并且仍然卡住。我会告诉你我遇到了什么。

我发现了同样的问题,为此我把头撞在墙上几个小时。我最终找到了一篇文章,其中有人谈到了 xml 中的类型转换。我准备在声明它们时传入子类和父类,并在构造函数中将它们都设置为同一个对象。这是一个选项,但不是一个优雅的选项。

首先是问题 xml 数据绑定还不够智能,无法在 xml 的编译时使用数据类创建来抓取基类。这是一个短板,希望他们能尽快解决。如果有人在解决此问题后阅读此内容,请随时更新帖子;)。

现在是解决方案 基本上你有两个选择。

选项 1

您可以像这样在 xml 中声明这两个变量:

 <data>
    <variable name="parentPropertyModel" type="com.mypath.BaseModel"/>
    <variable name="childPropertyModel" type="com.mypath.ChildModel"/>
</data>

然后在你的 onCreate 中你会使用 set both。

 override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    mBinding = DataBindingUtil.setContentView(this, R.layout.activity_myscreen)
    mBinding.childPropertyModel = mSelectedObject
    mBinding.parentPropertyModel = mSelectedObject
}

那么你当然会使用你所接触的财产所需要的那个。

android:text="@{childPropertyModel.fieldInChild}"
android:hint="@{parentPropertyModel.fieldInParent}"

现在我不了解你,但我不喜欢这样,因为它给未来的开发人员带来了两个不同对象的错觉,如果你没有很好地命名它们可能会造成混淆。所以我选择了选项 2。

选项 2

类型转换,我试了一下,它成功了 :)。你不会得到智能感知,所以你只需要知道你在输入什么,但我向你保证它是有效的。

像以前一样声明你的变量。

<data>
     <variable name="classModel" type="com.mypath.ChildModel"/>
</data>

然后像以前一样在 onCreate 中设置它,但现在只有一个对象。

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_myscreen)
        mBinding.classModel = mSelectedObject
 }

然后根据需要使用它,像这个完全限定的路径一样进行强制转换。

android:text="@{classModel.fieldInChild}"
android:hint="@{((com.mypath.BaseModel)classModel).fieldInParent}"

就是这样,我敢肯定,这不是你见过的最漂亮的东西,但它确实有效。

我希望这可以节省我忍受头痛的时间,哈哈。

编码愉快。

【讨论】:

    【解决方案2】:

    将 id 中的产品类设为公开,并提供数据并绑定到 xml。

    public int id;
    

    在xml中

     android:text="@{catalogItem.id}"
    

    【讨论】:

    • 这是解决方案。完全正确。如果你想要两种方式绑定,你可以做 android:text="@={catalogItem.id}"
    【解决方案3】:

    访问任何属性都没有这样的问题,它并不都与它们的访问修饰符有关,它只需要可以从Binding类访问的适当的getter方法。由于id是int,它只需要String转换器。

    【讨论】:

      【解决方案4】:

      使父类的字段受到保护。子类只能访问受保护或公共字段。

      protected int id;
      

      【讨论】:

        猜你喜欢
        • 2019-01-24
        • 2018-02-16
        • 2015-08-13
        • 2011-08-25
        • 1970-01-01
        • 1970-01-01
        • 2016-10-12
        • 2016-06-23
        • 2020-11-26
        相关资源
        最近更新 更多