资源包装密封类,数据绑定错误

问题描述 投票:0回答:2

我在使用

Resource
包裹我的数据时遇到了一个小问题,我不知道如何在我的数据绑定中使用它。

密封类

sealed class Resource<out T: Any> {
    data class Success<out T: Any>(val data: T): Resource<T>()
    data class Error(val exception: Throwable): Resource<Nothing>()
    object Loading: Resource<Nothing>()
}

我有这个

val product: LiveData<Resource<NetworkProductDetails>>

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="viewModel"
            type="my.package.ProductDetailsViewModel" />
    </data>

    <TextView
        android:id="@+id/product_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{viewModel.product.productName}"
        android:textAppearance="?attr/textAppearanceBody1"
        android:gravity="center"/>

    ...
</layout>

我遇到了一个问题,因为

viewModel.product
不是
NetworkProductDetails
而是
Resource<NetworkProductDetails>
并且我的 XML/数据绑定不知道如何处理它。


我找到了一种工作方式,但我想知道是否有更优雅的方式。

第一个解决方案:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="viewModel"
            type="my.package.ProductDetailsViewModel" />
        <variable
            name="product"
            type="my.package.NetworkProductDetails" />
    </data>

    <TextView
        android:id="@+id/product_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{product.productName}"
        android:textAppearance="?attr/textAppearanceBody1"
        android:gravity="center"/>

    ...
</layout>
viewModel.product.observe(viewLifecycleOwner, Observer { it ->
    when(it) {
        is Resource.Success -> {
            binding.product = it.data
        }
    }
}

第二种解决方案:

在我发表的评论中。

android android-databinding sealed-class
2个回答
7
投票

我遇到了一个问题,因为 viewModel.product 不是 NetworkProductDetails 而是 Resource,而我的 XML/数据绑定不知道如何处理它。

您错过了

data
。即使你最终得到了
Resource.Success
productName
也不是
Resource
甚至
Resource.Success
的属性。
data
Resource.Success
的属性,我假设
productName
NetworkProductDetails
的属性。你的表情没有
data

您还需要教授有关其他两种情况(

Loading
Error
)的数据绑定以及在其中执行的操作。

在最好的情况下,您也许能够实现如下所示的绑定表达式:

android:text='@{viewModel.product instanceof Resource.Success ? viewModel.product.data.productName : "like, whatever"}'

但是:

  • 我不知道

    instanceof
    是否能很好地处理通用问题

  • 我不知道你是否可以在一个表达式中引用两次

    LiveData
    输出

或者,您可以尝试为

Resource<NetworkProductDetails>
创建一个绑定适配器来处理这三种情况,尽管我从未尝试过使用泛型的类型。


3
投票

环顾四周后,我发现了两个解决方案,第一个是我原来的帖子,第二个是下面的:

在我的密封类中创建一个函数来公开数据(如果是),然后能够在我的

Success
中使用它
优点:

无需创建一个特殊的
    xml
  • 来隐藏一些逻辑
    无需像解决方案 1 那样在每个 
  • BindingAdapter
  • 中添加更多代码
    
    
  • 缺点:

我觉得它破坏了包装纸的意义
  • Fragment
sealed class Resource<out T: Any> {
    data class Success<out T: Any>(val data: T): Resource<T>()
    data class Error(val exception: Throwable): Resource<Nothing>()
    object Loading: Resource<Nothing>()

    fun toData(): T? = if(this is Success) this.data else null
}
	
© www.soinside.com 2019 - 2024. All rights reserved.